home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Educational / RasMol / Source / outfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-10  |  62.7 KB  |  2,709 lines

  1. /* outfile.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, August 1995
  4.  * Version 2.6
  5.  */
  6. #define OUTFILE
  7. #include "rasmol.h"
  8.  
  9. #ifdef IBMPC
  10. #include <windows.h>
  11. #include <malloc.h>
  12. #endif
  13. #ifdef APPLEMAC
  14. #include <Types.h>
  15. #include <Errors.h>
  16. #ifdef __CONDITIONALMACROS__
  17. #include <Printing.h>
  18. #else
  19. #include <PrintTraps.h>
  20. #endif
  21. #endif
  22. #ifndef sun386
  23. #include <stdlib.h>
  24. #endif
  25.  
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #include <math.h>
  29.  
  30. #include "outfile.h"
  31. #include "molecule.h"
  32. #include "command.h"
  33. #include "abstree.h"
  34. #include "transfor.h"
  35. #include "render.h"
  36. #include "repres.h"
  37. #include "graphics.h"
  38. #include "pixutils.h"
  39. #include "script.h"
  40.  
  41.  
  42. #ifdef EIGHTBIT
  43. #define RComp(x)   (RLut[LutInv[x]])
  44. #define GComp(x)   (GLut[LutInv[x]])
  45. #define BComp(x)   (BLut[LutInv[x]])
  46. #else
  47. #define RComp(x)   (((x)>>16)&0xff)
  48. #define GComp(x)   (((x)>>8)&0xff)
  49. #define BComp(x)   ((x)&0xff)
  50. #endif
  51.  
  52.  
  53. #ifdef INVERT
  54. #define InvertY(y) (y)
  55. #else
  56. #define InvertY(y) (-(y))
  57. #endif
  58.  
  59.  
  60. /* Sun rasterfile.h macro defns */
  61. #define RAS_MAGIC       0x59a66a95
  62. #define RAS_RLE         0x80
  63. #define RT_STANDARD     1
  64. #define RT_BYTE_ENCODED 2
  65. #define RMT_NONE        0
  66. #define RMT_EQUAL_RGB   1
  67.  
  68. /* Standard A4 size page: 8.267x11.811 inches */
  69. /* U.S. Normal size page: 8.500x11.000 inches */
  70. #define PAGEHIGH  (11.811*72.0)
  71. #define PAGEWIDE  (8.267*72.0)
  72. #define BORDER    0.90
  73.  
  74. /* Compression Ratio   0<x<127 */
  75. #define EPSFCompRatio  32
  76.  
  77. #define Round(x)       ((int)(x))
  78.  
  79.  
  80. #define PSBond      0x00
  81. #define PSHBond     0x01
  82. #define PSSSBond    0x02
  83. #define PSAtom      0x03
  84. #define PSRibbon    0x04
  85. #define PSMonit     0x05
  86.  
  87.  
  88.  
  89. typedef void __far* PSItemPtr;
  90.  
  91.  
  92. #if defined(IBMPC) || defined(APPLEMAC)
  93. static short __far *ABranch;
  94. static short __far *DBranch;
  95. static short __far *Hash;
  96. static Byte __far *Node;
  97. #else
  98. static short ABranch[4096];
  99. static short DBranch[4096];
  100. static short Hash[256];
  101. static Byte Node[4096];
  102. #endif
  103.  
  104.  
  105. /* Apple PICT macros */
  106. #define PICTcliprgn         0x0001
  107. #define PICTpicversion      0x0011
  108. #define PICTpackbitsrect    0x0098
  109. #define PICTdirectbitsrect  0x009a
  110. #define PICTendofpict       0x00ff
  111. #define PICTheaderop        0x0c00
  112.  
  113. typedef struct {
  114.     Byte len;
  115.     Byte ch;
  116.     } BMPPacket;
  117.     
  118.  
  119. static BMPPacket BMPBuffer[10];
  120. static int BMPCount,BMPTotal;        
  121. static int BMPPad;
  122.  
  123. static int GIFClrCode; 
  124. static int GIFEOFCode;
  125.  
  126. static short RLELineSize;
  127. static Card RLEFileSize;
  128. static int RLEEncode;
  129. static int RLEOutput;
  130. static int RLELength;
  131. static int RLEPixel;
  132. static int RLEChar;
  133.  
  134.  
  135. static Byte Buffer[256];
  136. static Byte LutInv[256];
  137. static int LineLength;
  138. static FILE *OutFile;
  139. static Card BitBuffer;
  140. static int BitBufLen;
  141. static int PacketLen;
  142. static int CodeSize;
  143.  
  144. static Real LineWidth;
  145. static int VectSolid;
  146. static int VectCol;
  147.  
  148. /* Macros for commonly used loops */
  149. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  150.              for(group=chain->glist;group;group=group->gnext)    \
  151.              for(aptr=group->alist;aptr;aptr=aptr->anext)
  152. #define ForEachBond  for(bptr=Database->blist;bptr;bptr=bptr->bnext)
  153. #define ForEachBack  for(chain=Database->clist;chain;chain=chain->cnext) \
  154.              for(bptr=chain->blist;bptr;bptr=bptr->bnext)
  155.  
  156.  
  157.  
  158. #ifdef APPLEMAC
  159. /* External RasMac Function Declaration! */
  160. void SetFileInfo( char*, OSType, OSType, short );
  161. #endif
  162.  
  163. static void FatalOutputError( ptr )
  164.     char *ptr;
  165. {
  166.     if( CommandActive ) WriteChar('\n');
  167.     WriteString("Output Error: Unable to create file `");
  168.     WriteString( ptr );  WriteString("'!\n");
  169.     CommandActive = False;
  170. }
  171.  
  172.  
  173. /*  Integer Output Routines  */
  174. #ifdef FUNCPROTO
  175. static void WriteLSBLong( Card );
  176. static void WriteMSBLong( Card );
  177. #endif
  178.  
  179. static void WriteByte( val )
  180.     int val;
  181. {
  182.     putc( val, OutFile );
  183. }
  184.  
  185. static void WriteLSBShort( val )
  186.     int val;
  187. {
  188.     putc( val&0xff, OutFile );
  189.     putc( (val>>8)&0xff, OutFile );
  190. }
  191.  
  192. static void WriteMSBShort( val )
  193.     int val;
  194. {
  195.     putc( (val>>8)&0xff, OutFile );
  196.     putc( val&0xff, OutFile );
  197. }
  198.  
  199. static void WriteLSBLong( val )
  200.     Card val;
  201. {
  202.     putc((int)(val&0xff),OutFile);
  203.     putc((int)((val>>8) &0xff),OutFile);
  204.     putc((int)((val>>16)&0xff),OutFile);
  205.     putc((int)((val>>24)&0xff),OutFile);
  206. }
  207.  
  208. static void WriteMSBLong( val )
  209.     Card val;
  210. {
  211.     putc((int)((val>>24)&0xff),OutFile);
  212.     putc((int)((val>>16)&0xff),OutFile);
  213.     putc((int)((val>>8) &0xff),OutFile);
  214.     putc((int)(val&0xff),OutFile);
  215. }
  216.  
  217.  
  218. static void CalcInvColourMap()
  219. {
  220. #ifdef EIGHTBIT
  221.     register int i;
  222.  
  223.     for( i=0; i<256; i++ )
  224.         if( ULut[i] )
  225.             LutInv[Lut[i]] = i;
  226. #endif
  227. }
  228.  
  229.  
  230. #ifdef EIGHTBIT
  231. static int CompactColourMap()
  232. {
  233.     register Pixel __huge *ptr;
  234.     register Long pos, count;
  235.     register int i, cols;
  236.  
  237.     CalcInvColourMap();
  238.     for( i=0; i<256; i++ )
  239.     {   Buffer[i] = 0;
  240.     Node[i] = 5;
  241.     }
  242.  
  243. #ifdef IBMPC
  244.     ptr = (Pixel __huge*)GlobalLock(FBufHandle);    
  245. #else
  246.     ptr = FBuffer;
  247. #endif
  248.  
  249.     cols = 0;
  250.     count = (Long)XRange*YRange;
  251.     for( pos=0; pos<count; pos++ )
  252.     {   i = LutInv[*ptr++];
  253.     if( !Buffer[i] ) 
  254.     {   Node[cols++] = i;
  255.         Buffer[i] = cols;
  256.     }
  257.     }
  258.  
  259.     for( i=0; i<256; i++ )
  260.     LutInv[i] = Buffer[LutInv[i]]-1;
  261. #ifdef IBMPC
  262.     GlobalUnlock(FBufHandle);
  263. #endif
  264.     return( cols );
  265. }
  266. #endif
  267.  
  268.  
  269.  
  270.  
  271. static void WritePPMWord( i )
  272.     int i;
  273. {
  274.     if( i>99 )
  275.     {   putc((i/100)+'0',OutFile); i %= 100;
  276.     putc((i/10) +'0',OutFile); i %= 10;
  277.     } else if( i>9 )
  278.     {   putc((i/10)+'0',OutFile);  i %= 10;
  279.     }
  280.     putc(i+'0',OutFile);
  281. }
  282.  
  283.  
  284. int WritePPMFile( name, raw )
  285.     char *name;  int raw;
  286. {
  287.     register Pixel __huge *ptr;
  288.     register int i,col;
  289.     register int x,y;
  290.  
  291. #if defined(IBMPC) || defined(APPLEMAC)
  292.     OutFile = fopen(name, (raw?"wb":"w") );
  293. #else
  294.     OutFile = fopen(name,"w");
  295. #endif
  296.  
  297.     if( !OutFile ) 
  298.     {   FatalOutputError(name);
  299.     return( False );
  300.     }
  301.  
  302.     CalcInvColourMap();
  303.     fprintf(OutFile,"P%c %d %d 255\n",(raw?'6':'3'),XRange,YRange);
  304.  
  305. #ifdef IBMPC
  306.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  307. #endif
  308.  
  309. #ifndef INVERT
  310.     ptr = FBuffer;
  311. #endif
  312.  
  313.     if( !raw )
  314.     {   col = 0;
  315.     for( y=YRange-1; y>=0; y-- )
  316.     {
  317. #ifdef INVERT
  318.         ptr = FBuffer + (Long)y*XRange;
  319. #endif
  320.         for( x=0; x<XRange; x++ )
  321.         {   i = *ptr++;
  322.         WritePPMWord((int)RComp(i));  WriteByte(' ');
  323.         WritePPMWord((int)GComp(i));  WriteByte(' ');
  324.         WritePPMWord((int)BComp(i));  
  325.         if( ++col == 5 )
  326.         {   WriteByte('\n');
  327.                     col = 0;
  328.         } else WriteByte(' ');
  329.         }
  330.     }
  331.     } else
  332.     for( y=YRange-1; y>=0; y-- )
  333.     {
  334. #ifdef INVERT
  335.         ptr = FBuffer + (Long)y*XRange;
  336. #endif
  337.         for( x=0; x<XRange; x++ )
  338.         {   i = *ptr++;
  339.         putc((int)RComp(i),OutFile);
  340.         putc((int)GComp(i),OutFile);
  341.         putc((int)BComp(i),OutFile);
  342.         }
  343.     }
  344.  
  345.     fclose(OutFile);
  346. #ifdef APPLEMAC
  347.     /* Avoid ANSI trigraph problems! */
  348.     SetFileInfo(name,'\?\?\?\?','\?\?\?\?',134);
  349. #endif
  350. #ifdef IBMPC
  351.     GlobalUnlock(FBufHandle); 
  352. #endif
  353.     return( True );
  354. }
  355.  
  356.  
  357. static void WriteGIFCode( code )
  358.     int code;
  359. {
  360.     register int max;
  361.  
  362.     max = (code==GIFEOFCode)? 0 : 7;
  363.     BitBuffer |= ((Card)code<<BitBufLen);
  364.     BitBufLen += CodeSize;
  365.  
  366.     while( BitBufLen > max )
  367.     {    
  368. #ifdef IBMPC
  369.      Buffer[PacketLen++]=(Byte)(BitBuffer&0xff);
  370. #else
  371.      Buffer[PacketLen++]=BitBuffer;
  372. #endif
  373.      BitBuffer >>= 8;
  374.      BitBufLen -= 8;
  375.  
  376.     if( PacketLen==255 )
  377.     {   WriteByte(0xff);
  378.         fwrite((char*)Buffer,1,255,OutFile);
  379.         PacketLen = 0;
  380.     }
  381.     }
  382. }
  383.  
  384. int WriteGIFFile( name )
  385.     char *name;
  386. {
  387.     register int i,j,cols;
  388.     register int pref,next,last;
  389.     register int isize, ilast;
  390.     register Pixel __huge *ptr;
  391.     register short __far *prev;
  392.     register int x,y,init;
  393.  
  394. #ifdef EIGHTBIT
  395.     cols = CompactColourMap();
  396.     if( cols<2 ) return( False );
  397.  
  398.     for( isize=2; isize<8; isize++ )
  399.     if( (1<<isize) >= cols ) break;
  400.     cols = 1<<isize;
  401.  
  402. #if defined(IBMPC) || defined(APPLEMAC)
  403.     OutFile = fopen(name,"wb");
  404. #else
  405.     OutFile = fopen(name,"w");
  406. #endif
  407.     if( !OutFile ) 
  408.     {    FatalOutputError(name);
  409.      return( False );
  410.     }
  411.     fputs("GIF87a",OutFile);
  412.     WriteLSBShort(XRange);
  413.     WriteLSBShort(YRange);
  414.     WriteByte(0xf0|(isize-1)); 
  415.     WriteByte(0x00); 
  416.     WriteByte(0x00);
  417.  
  418.     for( j=0; j<cols; j++ )
  419.     {   i = Node[j];
  420.     WriteByte(RLut[i]);
  421.     WriteByte(GLut[i]);
  422.     WriteByte(BLut[i]);
  423.     }
  424.  
  425.     WriteByte(',');
  426.     WriteByte(0x00);  WriteByte(0x00);
  427.     WriteByte(0x00);  WriteByte(0x00);
  428.     WriteLSBShort(XRange);
  429.     WriteLSBShort(YRange);
  430.     WriteByte(0x00);  WriteByte(isize);
  431.  
  432.     PacketLen=0;
  433.     BitBuffer=0;
  434.     BitBufLen=0;
  435.  
  436.     GIFClrCode = (1<<isize);
  437.     GIFEOFCode = GIFClrCode+1;
  438.     ilast = (GIFClrCode<<1)-GIFEOFCode;
  439.     isize++;
  440.  
  441.     CodeSize = isize;
  442.     last = ilast;
  443.     next = 1;  
  444.    
  445.     WriteGIFCode(GIFClrCode);
  446.     for( i=0; i<cols; i++ )
  447.     Hash[i]=0;
  448.  
  449. #ifdef IBMPC
  450.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);    
  451. #endif
  452.  
  453. #ifndef INVERT
  454.     ptr = FBuffer;
  455. #endif
  456.  
  457.     /* Avoid Warnings! */
  458.     prev = (short __far*)0; 
  459.     pref = 0;
  460.  
  461.     init = False;
  462.     for( y=YRange-1; y>=0; y-- )
  463.     {   
  464. #ifdef INVERT
  465.     ptr = FBuffer + (Long)y*XRange;
  466. #endif
  467.     for( x=0; x<XRange; x++ )
  468.     {   if( !init )
  469.         {   pref = LutInv[*ptr++];
  470.         prev = Hash+pref;
  471.         init = True;
  472.         continue;
  473.         }
  474.  
  475.         i = LutInv[*ptr++];
  476.  
  477.         while( *prev && (Node[*prev] != (Byte)i) )
  478.         prev = ABranch+*prev;
  479.  
  480.         if( *prev )
  481.         {   pref = *prev+GIFEOFCode;
  482.         prev = DBranch+*prev;
  483.         } else
  484.         {   WriteGIFCode(pref);
  485.         if( next==last )
  486.         {   if( CodeSize==12 )
  487.             {   WriteGIFCode(GIFClrCode);
  488.             pref = i;  prev = Hash+i;
  489.             for( i=0; i<cols; i++ )
  490.                 Hash[i] = 0;
  491.             CodeSize = isize;
  492.             last = ilast;
  493.             next = 1; 
  494.             continue;
  495.             }
  496.             last = (last<<1)+GIFEOFCode;
  497.             CodeSize++;
  498.         }
  499.         *prev = next;
  500.         ABranch[next] = 0;
  501.         DBranch[next] = 0;
  502.         Node[next] = i;
  503.         prev = Hash+i;
  504.         pref = i;
  505.         next++;
  506.         }
  507.     }
  508.     }
  509.  
  510.  
  511.     WriteGIFCode(pref);
  512.     WriteGIFCode(GIFEOFCode);
  513.     if( PacketLen )
  514.     {   WriteByte(PacketLen);
  515.     fwrite((char*)Buffer,1,PacketLen,OutFile);
  516.     }
  517.  
  518.     WriteByte(0x00);
  519.     WriteByte(';');
  520.     fclose(OutFile);
  521.  
  522. #ifdef APPLEMAC
  523.     /* Avoid ANSI trigraph problems! */
  524.     SetFileInfo(name,'\?\?\?\?','GIFf',134);
  525. #endif
  526. #ifdef IBMPC
  527.     GlobalUnlock(FBufHandle);
  528. #endif
  529.     return( True );
  530. #else
  531.     if( CommandActive ) WriteChar('\n');
  532.     WriteString("Output Error: 24 bit GIF files unsupported!\n");
  533.     CommandActive = False;
  534.     return( False );
  535. #endif
  536. }
  537.  
  538.  
  539.  
  540. static void FlushRastRLE()
  541. {
  542.     if( RLEChar==RAS_RLE )
  543.     {   if( RLEOutput )
  544.     {   WriteByte(RAS_RLE);
  545.         WriteByte(RLELength-1);
  546.         if( RLELength!=1 )
  547.         WriteByte(RAS_RLE);
  548.     } else RLEFileSize += (RLELength>1)? 3 : 2;
  549.     } else
  550.     if( RLEOutput )
  551.     {   if( RLELength>2 )
  552.         {   WriteByte(RAS_RLE);
  553.         WriteByte(RLELength-1);
  554.         } else if( RLELength==2 )
  555.         WriteByte(RLEChar);
  556.         WriteByte(RLEChar);
  557.     } else RLEFileSize += MinFun(RLELength,3);
  558. }
  559.  
  560.  
  561. static void WriteRastRLECode( val )
  562.     int val;
  563. {
  564.     if( RLEEncode )
  565.     {   if( !RLELength )
  566.     {   RLELength = 1;
  567.         RLEChar = val;
  568.     } else if( (RLEChar!=val) || (RLELength==256) )
  569.     {   FlushRastRLE();
  570.             RLELength = 1;
  571.             RLEChar = val;
  572.         } else RLELength++;
  573.     } else WriteByte(val);
  574. }
  575.  
  576. static void WriteRastRLEPad()
  577. {
  578.     if( RLEEncode )
  579.     {   if( !RLELength || (RLELength==256) )
  580.     {   WriteRastRLECode(0x00);
  581.     } else RLELength++;
  582.     } else WriteByte(0x00);
  583. }
  584.  
  585.  
  586. static void WriteRastData( output )
  587.     int output;
  588. {
  589.     register Pixel __huge *ptr;
  590.     register int x,y,pad;
  591. #ifndef EIGHTBIT
  592.     register int i;
  593. #endif
  594.  
  595. #ifdef IBMPC
  596.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  597. #endif
  598.  
  599. #ifndef INVERT
  600.     ptr = FBuffer;
  601. #endif
  602.  
  603.     pad = XRange%2;
  604.  
  605.     RLEOutput = output;
  606.     RLEFileSize = 0;
  607.     RLELength = 0;
  608.  
  609.     for( y=YRange-1; y>=0; y-- )
  610.     {   
  611. #ifdef INVERT
  612.     ptr = FBuffer + (Long)y*XRange;
  613. #endif
  614.     for( x=0; x<XRange; x++ )
  615. #ifndef EIGHTBIT
  616.     {   i = *ptr++;
  617.         WriteRastRLECode((int)BComp(i));
  618.         WriteRastRLECode((int)GComp(i));
  619.         WriteRastRLECode((int)RComp(i));
  620.     }
  621. #else
  622.         WriteRastRLECode((int)LutInv[*ptr++]);
  623. #endif
  624.     if( pad ) WriteRastRLEPad();
  625.     }
  626.  
  627.     if( RLEEncode && RLELength )
  628.     FlushRastRLE();
  629. #ifdef IBMPC
  630.     GlobalUnlock(FBufHandle);
  631. #endif
  632. }
  633.  
  634.  
  635.  
  636. int WriteRastFile( name, encode )
  637.     char *name;
  638.     int encode;
  639. {
  640.     register int i,size,cols;
  641.  
  642. #if defined(IBMPC) || defined(APPLEMAC)
  643.     OutFile = fopen(name,"wb");
  644. #else
  645.     OutFile = fopen(name,"w");
  646. #endif
  647.  
  648.     if( !OutFile )
  649.     {   FatalOutputError(name);
  650.     return(False);
  651.     }
  652.     WriteMSBLong( RAS_MAGIC );
  653.     WriteMSBLong(XRange);  
  654.     WriteMSBLong(YRange);
  655.     RLEEncode = encode;
  656.  
  657.  
  658. #ifdef EIGHTBIT
  659.     WriteMSBLong(8);
  660.  
  661.     if( encode )
  662.     {   WriteRastData(False);
  663.     WriteMSBLong(RLEFileSize);
  664.     WriteMSBLong(RT_BYTE_ENCODED);
  665.     } else
  666.     {   size = (XRange%2)? XRange+1 : XRange;
  667.     WriteMSBLong(size*YRange);
  668.     WriteMSBLong(RT_STANDARD);
  669.     }
  670.  
  671.     cols = CompactColourMap();
  672.     WriteMSBLong(RMT_EQUAL_RGB);
  673.     WriteMSBLong(cols*3);
  674.  
  675.     for( i=0; i<cols; i++ ) WriteByte(RLut[Node[i]]);
  676.     for( i=0; i<cols; i++ ) WriteByte(GLut[Node[i]]);
  677.     for( i=0; i<cols; i++ ) WriteByte(BLut[Node[i]]);
  678. #else
  679.     WriteMSBLong(24);
  680.  
  681.     if( encode )
  682.     {   WriteRastData(False);
  683.     WriteMSBLong(RLEFileSize);
  684.     WriteMSBLong(RT_BYTE_ENCODED);
  685.     } else
  686.     {   size = XRange*3;
  687.     if( size&1 ) size++;
  688.     WriteMSBLong((Long)size*YRange);
  689.     WriteMSBLong(RT_STANDARD);
  690.     }
  691.     WriteMSBLong(RMT_NONE);
  692.     WriteMSBLong(0);
  693. #endif
  694.  
  695.     WriteRastData(True);
  696.     fclose( OutFile );
  697. #ifdef APPLEMAC
  698.     /* Avoid ANSI trigraph problems! */
  699.     SetFileInfo(name,'\?\?\?\?','\?\?\?\?',134);
  700. #endif
  701.     return( True );
  702. }
  703.  
  704.  
  705. static void OutputEPSFByte( val )
  706.     int val;
  707. {
  708.     static char *hex = "0123456789ABCDEF";
  709.  
  710.     WriteByte( hex[val>>4] );
  711.     WriteByte( hex[val&0x0f] );
  712.     if( (LineLength+=2) > 72 )
  713.     {   WriteByte('\n');
  714.     LineLength = 0;
  715.     }
  716. }
  717.  
  718. static void EncodeEPSFPixel( val, col )
  719.     int val, col;
  720. {
  721.     register int r, g, b;
  722.     register int i;
  723.  
  724.     r = RComp(val);
  725.     g = GComp(val);
  726.     b = BComp(val);
  727.  
  728.     if( col )
  729.     {   OutputEPSFByte( r );
  730.     OutputEPSFByte( g );
  731.     OutputEPSFByte( b );
  732.     } else
  733.     {   i = (20*r + 32*g + 12*b)>>6;
  734.     OutputEPSFByte( i );
  735.     }
  736. }
  737.  
  738. int WriteEPSFFile( name, col, compr )
  739.     char *name;  int col, compr;
  740. {
  741.     register int x, y, i, j;
  742.     register int xsize, ysize;
  743.     register int xpos, ypos;
  744.     register int rotpage;
  745.  
  746.     register Pixel __huge *ptr;
  747.     int RLEBuffer[128];
  748.  
  749.     OutFile = fopen(name,"w");
  750.     if( !OutFile )
  751.     {   FatalOutputError(name);
  752.     return(False);
  753.     }
  754.  
  755.     CalcInvColourMap();
  756.     if( XRange <= YRange )
  757.     {   rotpage = False; 
  758.     xsize = XRange; 
  759.     ysize = YRange;
  760.     } else
  761.     {   rotpage = True;  
  762.     xsize = YRange; 
  763.     ysize = XRange;
  764.     }
  765.  
  766.     if( xsize > (int)(BORDER*PAGEWIDE) )
  767.     {   ysize = (int)(ysize*(BORDER*PAGEWIDE)/xsize);
  768.     xsize = (int)(BORDER*PAGEWIDE);
  769.     }
  770.     if( ysize > (int)(BORDER*PAGEHIGH) )
  771.     {   xsize = (int)(xsize*(BORDER*PAGEHIGH)/ysize);
  772.     ysize = (int)(BORDER*PAGEHIGH);
  773.     }
  774.  
  775.     xpos = (int)(PAGEWIDE-xsize)/2;
  776.     ypos = (int)(PAGEHIGH-ysize)/2;
  777.  
  778.     fputs("%!PS-Adobe-2.0 EPSF-2.0\n",OutFile);
  779.     fputs("%%Creator: RasMol Version 2.6\n",OutFile);
  780.     fprintf(OutFile,"%%%%Title: %s\n",name);
  781.     fprintf(OutFile,"%%%%BoundingBox: %d %d ",xpos,ypos);
  782.     fprintf(OutFile,"%d %d\n",xpos+xsize,ypos+ysize);
  783.  
  784.     fputs("%%Pages: 1\n",OutFile);
  785.     fputs("%%EndComments\n",OutFile);
  786.     fputs("%%EndProlog\n",OutFile);
  787.     fputs("%%Page: 1 1\n",OutFile);
  788.  
  789.     fputs("gsave\n",OutFile);
  790.     fputs("10 dict begin\n",OutFile);
  791.     fprintf(OutFile,"%d %d translate\n",xpos,ypos);
  792.     fprintf(OutFile,"%d %d scale\n",xsize,ysize);
  793.     if( rotpage )
  794.     {   fputs("0.5 0.5 translate\n",OutFile);
  795.     fputs("90 rotate\n",OutFile);
  796.     fputs("-0.5 -0.5 translate\n",OutFile);
  797.     }
  798.     fputc('\n',OutFile);
  799.  
  800.     if( compr )
  801.     {   fputs("/rlecount 0 def\n",OutFile);
  802.     fputs("/rlebyte 1 string def\n",OutFile);
  803.     fprintf(OutFile,"/pixbuf %d string def\n", col?3:1 );
  804.     fputs("/reppixel { pixbuf } def\n",OutFile);
  805.     fputs("/getpixel { \n",OutFile);
  806.     fputs("  currentfile pixbuf readhexstring pop\n",OutFile);
  807.     fputs("} def\n\n",OutFile);
  808.  
  809.     if( col )
  810.     {   fputs("/colorimage where {\n",OutFile);
  811.         fputs("  pop\n",OutFile);
  812.         fputs("} {\n",OutFile);
  813.         fputs("  /bytebuf 1 string def\n",OutFile);
  814.         fputs("  /colorimage { pop pop image } def\n",OutFile);
  815.         fputs("  /reppixel { bytebuf } def\n",OutFile);
  816.         fputs("  /getpixel {\n",OutFile);
  817.         fputs("    currentfile pixbuf readhexstring pop pop\n",OutFile);
  818.         fputs("    bytebuf 0\n",OutFile);
  819.         fputs("    pixbuf 0 get 20 mul\n",OutFile);
  820.         fputs("    pixbuf 1 get 32 mul\n",OutFile);
  821.         fputs("    pixbuf 2 get 12 mul\n",OutFile);
  822.         fputs("    add add -6 bitshift put bytebuf\n",OutFile);
  823.         fputs("  } def\n",OutFile);
  824.         fputs("} ifelse\n\n",OutFile);
  825.     }
  826.  
  827.     fputs("/rledecode {\n",OutFile);
  828.     fputs("  rlecount 0 eq {\n",OutFile);
  829.     fputs("    currentfile rlebyte readhexstring pop\n",OutFile);
  830.     fprintf(OutFile,"    0 get dup %d gt {\n",EPSFCompRatio);
  831.     fprintf(OutFile,"      /rlecount exch %d sub def\n",EPSFCompRatio);
  832.     fputs("      /rleflag true def\n",OutFile);
  833.     fputs("    } {\n",OutFile);
  834.     fputs("      /rlecount exch def\n",OutFile);
  835.     fputs("      /rleflag false def\n",OutFile);
  836.     fputs("    } ifelse getpixel\n",OutFile);
  837.     fputs("  } {\n",OutFile);
  838.     fputs("    /rlecount rlecount 1 sub def\n",OutFile);
  839.     fputs("    rleflag { reppixel } { getpixel } ifelse\n",OutFile);
  840.     fputs("  } ifelse\n",OutFile);
  841.     fputs("} def\n",OutFile);
  842.     } else if( col )
  843.     {   fprintf(OutFile,"/scanbuf %d string def\n",XRange*3);
  844.     fputs("/colorimage where {\n",OutFile);
  845.     fputs("  pop\n",OutFile);
  846.     fputs("} {\n",OutFile);
  847.     fputs("  /pixbuf 3 string def\n",OutFile);
  848.     fputs("  /bytebuf 1 string def\n",OutFile);
  849.     fputs("  /colorimage {\n",OutFile);
  850.     fputs("    pop pop pop {\n",OutFile);
  851.     fputs("      currentfile pixbuf readhexstring pop pop\n",OutFile);
  852.     fputs("      bytebuf 0\n",OutFile);
  853.     fputs("      pixbuf 0 get 20 mul\n",OutFile);
  854.     fputs("      pixbuf 1 get 32 mul\n",OutFile);
  855.     fputs("      pixbuf 2 get 12 mul\n",OutFile);
  856.     fputs("      add add -6 bitshift put bytebuf\n",OutFile);
  857.     fputs("    } image\n",OutFile);
  858.     fputs("  } def\n",OutFile);
  859.     fputs("} ifelse\n\n",OutFile);
  860.     } else fprintf(OutFile,"/scanbuf %d string def\n\n",XRange);
  861.  
  862.     fprintf(OutFile,"%d %d %d\n",XRange,YRange,8);
  863.     fprintf(OutFile,"[%d 0 0 -%d 0 %d]\n",XRange,YRange,YRange);
  864.  
  865.     if( !compr )
  866.     {   fputs("{ currentfile scanbuf readhexstring pop }\n",OutFile);
  867.     } else fputs("{ rledecode }\n",OutFile);
  868.     if( col ) fputs("false 3 color",OutFile);
  869.     fputs("image\n",OutFile);
  870.  
  871. #ifdef IBMPC
  872.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  873. #endif
  874.  
  875. #ifndef INVERT
  876.     ptr = FBuffer; 
  877. #endif
  878.  
  879.     RLELength = 0;
  880.     LineLength = 0;
  881.     for( y=YRange-1; y>=0; y-- )
  882.     {
  883. #ifdef INVERT
  884.     ptr = FBuffer + (Long)y*XRange;
  885. #endif
  886.     for( x=0; x<XRange; x++ )
  887.     {   i = *ptr++;
  888.         if( compr )
  889.         {   if( RLELength )
  890.         {   if( RLEEncode )
  891.             {   if( (RLEPixel!=i) || (RLELength==256-EPSFCompRatio) )
  892.             {   OutputEPSFByte(RLELength+EPSFCompRatio-1);
  893.                 EncodeEPSFPixel(RLEPixel,col);
  894.                 RLEEncode = False;
  895.                 RLEBuffer[0] = i;
  896.                 RLELength = 1;
  897.             } else RLELength++;
  898.             } else if( RLEBuffer[RLELength-1] == i )
  899.             {   if( RLELength>1 )
  900.             {   OutputEPSFByte(RLELength-2);
  901.                 for( j=0; j<RLELength-1; j++ )
  902.                 EncodeEPSFPixel(RLEBuffer[j],col);
  903.             }
  904.             RLEEncode = True;
  905.             RLELength = 2;
  906.             RLEPixel = i;
  907.             } else if( RLELength == EPSFCompRatio+1 )
  908.             {   OutputEPSFByte(EPSFCompRatio);
  909.             for( j=0; j<RLELength; j++ )
  910.                  EncodeEPSFPixel(RLEBuffer[j],col);
  911.             RLEEncode = False;
  912.             RLEBuffer[0] = i;
  913.             RLELength = 1;
  914.             } else RLEBuffer[RLELength++] = i;
  915.         } else
  916.         {   RLEEncode = False;
  917.             RLEBuffer[0] = i;
  918.             RLELength = 1;
  919.         }
  920.         } else EncodeEPSFPixel( i, col );
  921.     }
  922.     }
  923.  
  924.     if( compr && RLELength )
  925.     {   if( RLEEncode )
  926.     {   OutputEPSFByte(RLELength+EPSFCompRatio-1);
  927.         EncodeEPSFPixel(RLEPixel,col);
  928.     } else
  929.     {   OutputEPSFByte(RLELength-1);
  930.         for( j=0; j<RLELength; j++ )
  931.         EncodeEPSFPixel(RLEBuffer[j],col);
  932.     }
  933.     }
  934.  
  935.     if( LineLength ) 
  936.     fputc('\n',OutFile);
  937.     fputs("end\n",OutFile);
  938.     fputs("grestore\n",OutFile);
  939.     fputs("showpage\n",OutFile);
  940.     fputs("%%Trailer\n",OutFile);
  941.     fputs("%%EOF\n",OutFile);
  942.     fclose( OutFile );
  943. #ifdef APPLEMAC
  944.     /* Avoid ANSI trigraph problems! */
  945.     SetFileInfo(name,'vgrd','TEXT',134);
  946. #endif
  947. #ifdef IBMPC
  948.     GlobalUnlock(FBufHandle);
  949. #endif
  950.     return( True );
  951. }
  952.  
  953.  
  954.  
  955. /* Flush AbsMode buffer */
  956. static void FlushBMPBuffer()
  957. {
  958.     if( RLEOutput )
  959.     {   WriteByte(0x00);
  960.     WriteByte(PacketLen);
  961.     fwrite((char*)Buffer,1,PacketLen,OutFile);
  962.     if( PacketLen%2 ) WriteByte(0x00);    
  963.     } else
  964.     RLEFileSize += (PacketLen%2)+PacketLen+2;
  965.     PacketLen = 0;
  966. }
  967.  
  968. /* Flush RLEMode buffer */
  969. static void FlushBMPPackets()
  970. {
  971.     register int i;
  972.     
  973.     if( PacketLen )
  974.     FlushBMPBuffer();
  975.  
  976.     if( RLEOutput )
  977.     {   for( i=0; i<BMPCount; i++ )
  978.     {   WriteByte(BMPBuffer[i].len);
  979.         WriteByte(BMPBuffer[i].ch);
  980.     }
  981.     } else RLEFileSize += (BMPCount<<1);
  982.     BMPCount = BMPTotal = 0;
  983. }
  984.  
  985. static void ProcessBMPPacket()
  986. {
  987.     register int cost;
  988.     register int i,j;
  989.     
  990.     BMPBuffer[BMPCount].len = RLELength;
  991.     BMPBuffer[BMPCount].ch = RLEChar;
  992.     BMPTotal += RLELength;
  993.     RLELength = 0;
  994.     BMPCount++; 
  995.  
  996.  
  997.     /* RLEMode is more efficient */
  998.     if( BMPTotal > BMPCount+5 )
  999.     {   FlushBMPPackets();
  1000.     return;
  1001.     }
  1002.     
  1003.     /* Flush AbsMode buffer */
  1004.     if( PacketLen+BMPTotal>255 )
  1005.     FlushBMPBuffer();
  1006.     
  1007.  
  1008.     /* Cannot leave RLEMode */
  1009.     if( PacketLen+BMPTotal<3 )
  1010.     return;
  1011.     
  1012.     /* Determine AbsMode cost */
  1013.     if( PacketLen )
  1014.     {   cost = BMPTotal - (PacketLen%2);
  1015.     cost += (cost%2);
  1016.     } else cost = (BMPTotal%2)+BMPTotal+2;    
  1017.  
  1018.     /* Put RLE Packets into AbsMode buffer */
  1019.     if( cost <= (int)(BMPCount<<1) )
  1020.     {   for( i=0; i<BMPCount; i++ )
  1021.         for( j=0; j<(int)BMPBuffer[i].len; j++ )
  1022.         Buffer[PacketLen++] = BMPBuffer[i].ch;
  1023.     BMPCount = BMPTotal = 0;
  1024.     }
  1025. }
  1026.  
  1027. /* Collect pixels into RLE Packets */
  1028. static void WriteBMPCode( val )
  1029.     int val;
  1030. {
  1031.     if( !RLELength )
  1032.     {   RLELength = 1;
  1033.     RLEChar = val;
  1034.     } else
  1035.     if( (RLEChar!=val) || (RLELength==255) )
  1036.     {   ProcessBMPPacket();
  1037.         RLELength = 1;
  1038.         RLEChar = val;
  1039.     } else
  1040.         RLELength++;
  1041. }
  1042.  
  1043. static void WriteBMPData( output )
  1044.     int output;
  1045. {
  1046.     register Pixel __huge *ptr;
  1047.     register int x,y;
  1048.     
  1049.     RLEOutput = output;
  1050.     RLEFileSize = 0;   BMPCount = 0;
  1051.     RLELength = 0;     BMPTotal = 0;
  1052.     PacketLen = 0; 
  1053.  
  1054. #ifdef INVERT
  1055.     ptr = FBuffer;
  1056. #endif
  1057.  
  1058.     for( y=YRange-1; y>=0; y-- )
  1059.     {
  1060. #ifndef INVERT
  1061.     ptr = FBuffer + (Long)y*XRange;
  1062. #endif
  1063.     for( x=0; x<XRange; x++ )
  1064.         WriteBMPCode(LutInv[*ptr++]);
  1065.  
  1066.     for( x=0; x<BMPPad; x++ )
  1067.         WriteBMPCode(0x00);
  1068.  
  1069.     /* Flush RLE codes */
  1070.     ProcessBMPPacket();
  1071.     FlushBMPPackets();
  1072.     
  1073.     if( RLEOutput )
  1074.     {   /* End of line code */
  1075.         WriteByte(0x00);
  1076.         WriteByte(y?0x00:0x01);
  1077.     } else RLEFileSize += 2;
  1078.     }
  1079. }
  1080.  
  1081.  
  1082.     
  1083. int WriteBMPFile( name )
  1084.     char *name;
  1085. {
  1086.     register Pixel __huge *ptr;
  1087.     register int x,y,i,raw;
  1088.     register Card size;
  1089.  
  1090. #if defined(IBMPC) || defined(APPLEMAC)
  1091.     OutFile = fopen(name,"wb");
  1092. #else
  1093.     OutFile = fopen(name,"w");
  1094. #endif
  1095.     if( !OutFile )
  1096.     {    FatalOutputError(name);
  1097.      return( False );
  1098.     }
  1099.  
  1100. #ifdef EIGHTBIT
  1101. #ifdef IBMPC
  1102.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  1103. #endif
  1104.  
  1105.     CalcInvColourMap();
  1106.     /* zero-pad scanlines to long */
  1107.     BMPPad = XRange%4;
  1108.     if( BMPPad ) 
  1109.      BMPPad = 4-BMPPad; 
  1110.  
  1111.     WriteBMPData(False);
  1112.     size = (Long)(XRange+BMPPad)*YRange;
  1113.     if( RLEFileSize<size )
  1114.     {   size = RLEFileSize;
  1115.     raw = False;
  1116.     } else raw = True;
  1117.  
  1118.  
  1119.     WriteByte('B'); 
  1120.     WriteByte('M');
  1121.     WriteLSBLong(size+1078);
  1122.     WriteLSBLong((Card)0);
  1123.     WriteLSBLong((Card)1078);
  1124.  
  1125.     WriteLSBLong((Card)40);
  1126.     WriteLSBLong((Card)XRange);
  1127.     WriteLSBLong((Card)YRange);
  1128.     WriteByte(0x01);  WriteByte(0x00);
  1129.     WriteByte(0x08);  WriteByte(0x00);
  1130.     WriteLSBLong(raw? (Card)0 : (Card)1);
  1131.     WriteLSBLong(size);
  1132.     
  1133.     WriteLSBLong((Card)0);
  1134.     WriteLSBLong((Card)0);
  1135.     WriteLSBLong((Card)256);
  1136.     WriteLSBLong((Card)256);
  1137.  
  1138.     for( i=0; i<256; i++ )
  1139.     {   WriteByte(BLut[i]);
  1140.     WriteByte(GLut[i]);
  1141.     WriteByte(RLut[i]);
  1142.     WriteByte(0x00);
  1143.     }
  1144.  
  1145.     if( raw )
  1146.     {   
  1147. #ifdef INVERT
  1148.     ptr = FBuffer;
  1149. #endif
  1150.     for( y=YRange-1; y>=0; y-- )
  1151.     {
  1152. #ifndef INVERT
  1153.         ptr = FBuffer + (Long)y*XRange;
  1154. #endif
  1155.         for( x=0; x<XRange; x++ )
  1156.         WriteByte(LutInv[*ptr++]);
  1157.         for( x=0; x<BMPPad; x++ )
  1158.         WriteByte(0x00);
  1159.         WriteByte(0x00);
  1160.         WriteByte(y?0x00:0x01);
  1161.     }
  1162.     } else
  1163.     WriteBMPData(True);
  1164.     fclose(OutFile);
  1165.  
  1166. #ifdef APPLEMAC
  1167.     /* Avoid ANSI trigraph problems! */
  1168.     SetFileInfo(name,'\?\?\?\?','\?\?\?\?',134);
  1169. #endif
  1170. #ifdef IBMPC
  1171.     GlobalUnlock(FBufHandle);
  1172. #endif
  1173.     return(True);
  1174. #else
  1175.     if( CommandActive ) WriteChar('\n');
  1176.     WriteString("Output Error: 24 bit BMP files unsupported!\n");
  1177.     CommandActive = False;
  1178.     return( False );
  1179. #endif
  1180. }
  1181.  
  1182.  
  1183.  
  1184. #ifdef FUNCPROTO
  1185. static int FindDepth( PSItemPtr, int );
  1186. static void DepthSort( PSItemPtr __far*, char __far*, int );
  1187. #endif
  1188.  
  1189. static int FindDepth( item, type )
  1190.      PSItemPtr item;  int type;
  1191. {
  1192.     register HBond __far *hbond;
  1193.     register Atom __far *atom;
  1194.     register Bond __far *bond;
  1195.     register int result;
  1196.  
  1197.     switch( type )
  1198.     {   case(PSAtom):    atom = (Atom __far*)item;
  1199.                      return( atom->z );
  1200.  
  1201.         case(PSBond):    bond = (Bond __far*)item;
  1202.                      result = bond->srcatom->z;
  1203.                      if( result < bond->dstatom->z )
  1204.                          result = bond->dstatom->z;
  1205.                          return( result );
  1206.  
  1207.         case(PSSSBond):  
  1208.         case(PSHBond):   hbond = (HBond __far*)item;
  1209.                          if( (type==PSHBond)? HBondMode : SSBondMode )
  1210.                          {   result = hbond->srcCA->z;
  1211.                              if( result < hbond->dstCA->z )
  1212.                                  result = hbond->dstCA->z;
  1213.                          } else
  1214.                          {   result = hbond->src->z;
  1215.                              if( result < hbond->dst->z )
  1216.                                  result = hbond->dst->z;
  1217.                          }
  1218.                          return( result );
  1219.     }
  1220.     return( 0 );
  1221. }
  1222.  
  1223.  
  1224. static void DepthSort( data, type, count )
  1225.     PSItemPtr __far *data;
  1226.     char __far *type;
  1227.     int count;
  1228. {
  1229.     register char ttmp;
  1230.     register void __far *dtmp;
  1231.     register int i, j, k;
  1232.     register int depth;
  1233.     register int temp;
  1234.  
  1235.     for( i=1; i<count; i++ )
  1236.     {   dtmp = data[i];  
  1237.     ttmp = type[i];
  1238.  
  1239.     j = i-1;
  1240.     depth = FindDepth(dtmp,ttmp);
  1241.     temp = FindDepth(data[j],type[j]);
  1242.     while( (depth<temp) || ((depth==temp)&&(ttmp<type[j])) )
  1243.         if( j-- ) 
  1244.         {   temp = FindDepth(data[j],type[j]);
  1245.         } else break;
  1246.     j++;
  1247.  
  1248.     if( j != i )
  1249.     {   for( k=i; k>j; k-- )
  1250.         {    data[k] = data[k-1];
  1251.          type[k] = type[k-1];
  1252.         }
  1253.         data[j] = dtmp;
  1254.         type[j] = ttmp;
  1255.     }
  1256.     }
  1257. }
  1258.  
  1259. #ifdef FUNCPROTO
  1260. static int ClipVectSphere( Atom __far* );
  1261. static int ClipVectBond( Atom __far*, Atom __far* );
  1262.  
  1263. static void WriteVectSphere( PSItemPtr __far*, char __far*, int );
  1264. static void WriteVectStick( Atom __far*, Atom __far*, int, int );
  1265. static void WriteVectWire( Atom __far*, Atom __far*, int, int );
  1266.  
  1267. static Long CountPSItems();
  1268. static void FetchPSItems( PSItemPtr __far*, char __far* );
  1269. static void WritePSItems( PSItemPtr __far*, char __far*, int );
  1270. #endif
  1271.  
  1272.  
  1273. static int ClipVectSphere( ptr )
  1274.     Atom __far *ptr;
  1275. {
  1276.     register int rad;
  1277.  
  1278.     rad = ptr->irad;
  1279.  
  1280.     if( ptr->x + rad < 0 )  return( True );
  1281.     if( ptr->y + rad < 0 )  return( True );
  1282.     if( ptr->x - rad >= XRange )  return( True );
  1283.     if( ptr->y - rad >= YRange )  return( True );
  1284.     return( False );
  1285. }
  1286.  
  1287.  
  1288. static int ClipVectBond( src, dst )
  1289.     Atom __far *src;
  1290.     Atom __far *dst;
  1291. {
  1292.     if( !src || !dst )  return( True );
  1293.     if( (src->x<0) && (dst->x<0) )  return( True );
  1294.     if( (src->y<0) && (dst->y<0) )  return( True );
  1295.     if( (src->x>=XRange) && (dst->x>=XRange) )  return( True );
  1296.     if( (src->y>=YRange) && (dst->y>=YRange) )  return( True );
  1297.     return( False );
  1298. }
  1299.  
  1300.  
  1301.  
  1302. static void WriteVectColour( col )
  1303.     int col;
  1304. {
  1305.     if( col != VectCol )
  1306.     {   fprintf(OutFile,"%g ",(Real)RLut[col]/255.0);
  1307.     fprintf(OutFile,"%g ",(Real)GLut[col]/255.0);
  1308.     fprintf(OutFile,"%g ",(Real)BLut[col]/255.0);
  1309.     fputs("setrgbcolor\n",OutFile);
  1310.     VectCol = col;
  1311.     }
  1312. }
  1313.  
  1314.  
  1315. #define MAXSECT 5
  1316. typedef struct {
  1317.     /* Ellipse */
  1318.     Real ephi,epsi;
  1319.     Real etheta;
  1320.     Real ex,ey;
  1321.     Real erad;
  1322.  
  1323.     /* Sphere */
  1324.     Real sphi,spsi;
  1325.     int sx,sy;
  1326.     Real srad;
  1327.     } SphereSect;
  1328.  
  1329.  
  1330. static int VectClipContain( x, y )
  1331.     SphereSect *x; SphereSect *y;
  1332. {
  1333.     if( x->erad != 0.0 )
  1334.     {   if( y->erad != 0.0 )
  1335.         /* Simple segment containment test! */
  1336.         return( ((x->sphi+x->spsi)>=(y->sphi+y->spsi)) &&
  1337.             ((x->sphi-x->spsi)<=(y->sphi-y->spsi)) );
  1338.     } else if( y->erad == 0.0 )
  1339.     return( x->srad >= y->srad );
  1340.     return( False );
  1341. }
  1342.  
  1343.  
  1344. static void WriteVectSphere( data, type, index )
  1345.     PSItemPtr __far*data; 
  1346.     char __far *type;
  1347.     int index;
  1348. {
  1349.     register int ecount, count;
  1350.     register Atom __far *atm;
  1351.     register Atom __far *ptr;
  1352.     register Long dist2,dist3;
  1353.     register int dx, dy, dz;
  1354.     register int i,j,k;
  1355.  
  1356.     register Real b,d,f,g,x;
  1357.     register Real radf,radb;
  1358.     register Real phi1,phi2;
  1359.     register Real temp,psi;
  1360.     register Real theta;
  1361.  
  1362.     register SphereSect *sptr;
  1363.     SphereSect sect[MAXSECT];
  1364.  
  1365.     ptr = (Atom __far*)data[index];
  1366.     radf = ptr->radius*Scale;
  1367.  
  1368.     count = 0;
  1369.     ecount = 0;
  1370.     sptr = sect;
  1371.     for( i=index-1; i>=0; i-- )
  1372.     {   if( type[i] != PSAtom )
  1373.         continue;
  1374.  
  1375.     atm = (Atom __far*)data[i];
  1376.     /* Atom can't intersect visibly! */
  1377.     if( atm->z + atm->irad < ptr->z )
  1378.         continue;
  1379.  
  1380.     dx = atm->x - ptr->x; 
  1381.     dy = atm->y - ptr->y; 
  1382.     dz = atm->z - ptr->z;
  1383.  
  1384.     dist2 = (Long)dx*dx + (Long)dy*dy;
  1385.     dist3 = dist2 + dz*dz;
  1386.  
  1387.     radb = atm->radius*Scale;  
  1388.     temp = radf + radb;
  1389.  
  1390.     /* Atoms don't intersect! */
  1391.     if( dist3 > temp*temp ) continue;
  1392.  
  1393.  
  1394.     d = sqrt( (double)dist3 );
  1395.     f = (temp*(radf-radb)+dist3)/(2.0*d);
  1396.     theta = -dz/d;
  1397.  
  1398.     if( f>0 )
  1399.     {   temp = radf*radf;
  1400.         /* Intersection not visible! */
  1401.         if( theta*temp > temp-f*f )
  1402.         continue;
  1403.     } else if( f < -radf )
  1404.         return;
  1405.  
  1406.     x = sqrt( (radf-f)*(radf+f) );
  1407.  
  1408.     if( dx || dy )
  1409.     {   g = sqrt( (double)dist2 );
  1410.         psi = Rad2Deg*atan2(dy,dx);
  1411.         b = (f*(dz*dz))/(d*g);
  1412.  
  1413.         if( AbsFun(b)>x )
  1414.         continue;
  1415.  
  1416.         phi1 = b + (f*g)/d;
  1417.         phi1 = Rad2Deg*acos(phi1/radf);
  1418.         if( phi1!=phi1 ) continue;
  1419.  
  1420.         phi2 = (d*b)/g;
  1421.         if( AbsFun(phi2) < x )
  1422.         {   phi2 = Rad2Deg*acos(phi2/x);
  1423.         if( phi2!=phi2 ) continue;
  1424.         if( phi2 > 90.0 ) 
  1425.             phi2 = 180.0-phi1;
  1426.         } else phi2 = 90.0;
  1427.  
  1428.         sptr->erad = x;
  1429.         sptr->etheta = -theta;
  1430.         sptr->ephi = psi;
  1431.         sptr->epsi = phi2;
  1432.  
  1433.         temp = f/d;
  1434.         sptr->ex = ptr->x+temp*dx;
  1435.         sptr->ey = ptr->y+temp*dy;
  1436.  
  1437.         sptr->srad = radf;
  1438.         sptr->sphi = psi;
  1439.         sptr->spsi = phi1;
  1440.         sptr->sx = ptr->x;
  1441.         sptr->sy = ptr->y;
  1442.  
  1443.     } else
  1444.     {   x = sqrt( (radf-g)*(radf+g) );
  1445.  
  1446.         sptr->srad = x;
  1447.         sptr->erad = 0.0;
  1448.         sptr->sx = ptr->x;
  1449.         sptr->sy = ptr->y;
  1450.         sptr->sphi = 180;
  1451.         sptr->spsi = -180;
  1452.     }
  1453.  
  1454.     /* Optimize Segments */
  1455.     j = 0;
  1456.     while( j<count )
  1457.         if( VectClipContain(sptr,sect+j) )
  1458.         {   /* Delete Segment sect[j] */
  1459.         for( k=j; k<count; k++ )
  1460.             sect[k] = sect[k+1];
  1461.         count--;  sptr--;
  1462.         } else if( VectClipContain(sect+j,sptr) )
  1463.         {   break;  /* Exclude Segment */
  1464.         } else j++;
  1465.        
  1466.  
  1467.     if( j==count )
  1468.     {   count++;  sptr++;
  1469.         if( sptr->erad != 0.0 )
  1470.         ecount++;
  1471.         if( count==MAXSECT )
  1472.         break;
  1473.     }
  1474.     }
  1475.  
  1476.     if( UseOutLine )
  1477.     {   temp = (ptr->z-ZOffset)/ImageSize + 1.0;
  1478.     if( temp != LineWidth )
  1479.     {   fprintf(OutFile,"%g setlinewidth\n",temp);
  1480.         LineWidth = temp;
  1481.     }
  1482.     }
  1483.  
  1484.     if( !VectSolid )
  1485.     {   fputs("[] 0 setdash\n",OutFile);
  1486.         VectSolid = True;
  1487.     }
  1488.  
  1489.     if( count )
  1490.     {   fputs("gsave\n",OutFile);
  1491.     fprintf(OutFile,"%%%% %d %d\n",count,ecount);
  1492.  
  1493.     sptr = sect;
  1494.     for( i=0; i<count; i++ )
  1495.     {   if( sptr->erad != 0.0 )
  1496.         {   fprintf(OutFile,"%g %g %g %g %g %g ClipEllips\n",
  1497.                 sptr->erad,sptr->epsi,sptr->etheta,
  1498.                 sptr->ephi,sptr->ex,sptr->ey);
  1499.         }
  1500.  
  1501.         if( (i==count-1) || (sptr->erad==0.0) )
  1502.         {   fprintf(OutFile,"%g %g %g %d %d ClipSphere\n",sptr->srad,
  1503.                 sptr->sphi+sptr->spsi,sptr->sphi-sptr->spsi,
  1504.                 sptr->sx, sptr->sy );
  1505.         } else fprintf(OutFile,"%g %g %g %d %d ClipBox\n",
  1506.                     sptr->srad+sptr->srad+2,
  1507.                     sptr->srad+1, sptr->ephi,
  1508.                     sptr->sx, sptr->sy );
  1509.         sptr++;
  1510.     }
  1511.  
  1512.     i = ptr->col + ColourMask;
  1513.     fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
  1514.     fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
  1515.     fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
  1516.     fprintf(OutFile,"%g Shade\n",radf);
  1517.     fputs("grestore\n\n",OutFile);
  1518.     } else
  1519.     {   i = ptr->col + ColourMask;
  1520.     fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
  1521.     fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
  1522.     fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
  1523.     fprintf(OutFile,"%g %d %d ",radf,ptr->x,ptr->y);
  1524.     fputs("Sphere\n\n",OutFile);
  1525.     }
  1526. }
  1527.  
  1528.  
  1529. static void WriteVectWire( src, dst, col, dash )
  1530.     Atom __far *src;
  1531.     Atom __far *dst;
  1532.     int col, dash;
  1533. {
  1534.     register Atom __far *tmp;
  1535.     register Real radius;
  1536.     register Real temp;
  1537.     register Real dist;
  1538.  
  1539.     register Real midx, midy;
  1540.     register Real endx, endy;
  1541.     register int col1, col2;
  1542.     register int dx, dy, dz;
  1543.     register Long dist2;
  1544.  
  1545.  
  1546.     if( src->z > dst->z )
  1547.     {   tmp = src;
  1548.         src = dst;
  1549.     dst = tmp;
  1550.     }
  1551.  
  1552.     if( !col )
  1553.     {   col1 = src->col;
  1554.     col2 = dst->col;
  1555.     } else col1 = col2 = col;
  1556.  
  1557.     dx = dst->x - src->x;  
  1558.     dy = dst->y - src->y;
  1559.     dist2 = dx*dx + dy*dy;
  1560.     dist = sqrt( (double)dist2 );
  1561.  
  1562.     if( dst->flag & SphereFlag )
  1563.     {   radius = dst->radius*Scale;
  1564.     if( dist <= radius ) return;
  1565.  
  1566.     /* Test for second half obscured! */
  1567.     if( (col1!=col2) && (0.5*dist < radius) )
  1568.         col2 = col1;
  1569.     }
  1570.  
  1571.     if( src->flag & SphereFlag )
  1572.     {   radius = src->radius*Scale;
  1573.     if( dist <= radius ) return;
  1574.  
  1575.     /* Test for first half obscured! */
  1576.     if( (col1!=col2) && (0.5*dist < radius) )
  1577.         col1 = col2;
  1578.     }
  1579.  
  1580.  
  1581.     WriteVectColour( col1+ColourMask );
  1582.     temp = ((src->z-ZOffset)+(dst->z-ZOffset))/ImageSize + 1.0;
  1583.     if( temp != LineWidth )
  1584.     {   fprintf(OutFile,"%g setlinewidth\n",temp);
  1585.     LineWidth = temp;
  1586.     }
  1587.  
  1588.     if( dash )
  1589.     {   if( VectSolid )
  1590.         {   fputs("[3 3] 0 setdash\n",OutFile);
  1591.             VectSolid = False;
  1592.         }
  1593.     } else
  1594.         if( !VectSolid )
  1595.         {   fputs("[] 0 setdash\n",OutFile);
  1596.             VectSolid = True;
  1597.         }
  1598.  
  1599.  
  1600.     if( src->flag & SphereFlag )
  1601.     {   dz = dst->z - src->z;
  1602.     dist = sqrt( (double)(dist2 + dz*dz) );
  1603.     endx = src->x + (radius*dx)/dist;
  1604.     endy = src->y + (radius*dy)/dist;
  1605.     fprintf(OutFile,"%g %g ",endx,endy);
  1606.     } else
  1607.     fprintf(OutFile,"%d %d ",src->x,src->y);
  1608.  
  1609.     if( col1 != col2 )
  1610.     {   midx = 0.5*(src->x + dst->x);
  1611.     midy = 0.5*(src->y + dst->y);
  1612.     fprintf(OutFile,"%g %g Wire\n",midx,midy);
  1613.  
  1614.     WriteVectColour( col2+ColourMask );
  1615.     fprintf(OutFile,"%g %g ",midx,midy);
  1616.     } 
  1617.     fprintf(OutFile,"%d %d Wire\n",dst->x,dst->y);
  1618. }
  1619.  
  1620.  
  1621. static void WriteVectStick( src, dst, col, rad )
  1622.     Atom __far *src;  
  1623.     Atom __far *dst;
  1624.     int col, rad;
  1625. {
  1626.     register Atom __far *tmp;
  1627.     register Real midx, midy;
  1628.     register Real relx, rely;
  1629.     register Real endx, endy;
  1630.     register Real radius, angle;
  1631.     register Real dist, dist3;
  1632.     register Real temp, ratio;
  1633.  
  1634.     register Long dist2;
  1635.     register int dx, dy, dz;
  1636.     register int col1, col2;
  1637.     register int i, inten;
  1638.  
  1639.     if( !rad )
  1640.     {   WriteVectWire(src,dst,col,False);
  1641.     return;
  1642.     }
  1643.  
  1644.     if( src->z > dst->z )
  1645.     {   tmp = src;
  1646.         src = dst;
  1647.     dst = tmp;
  1648.     }
  1649.  
  1650.     if( !col )
  1651.     {   col1 = src->col;
  1652.     col2 = dst->col;
  1653.     } else col1 = col2 = col;
  1654.  
  1655.     dx = dst->x - src->x;  
  1656.     dy = dst->y - src->y;
  1657.     dz = dst->z - src->z;
  1658.     dist2 = dx*dx + dy*dy;
  1659.     dist3 = sqrt( (double)(dist2 + dz*dz) );
  1660.     dist = sqrt( (double)dist2 );
  1661.  
  1662.     if( dst->flag & SphereFlag )
  1663.     {   radius = dst->radius*Scale;
  1664.     if( dist <= radius ) return;
  1665.  
  1666.     /* Test for nearest half obscured! */
  1667.     if( (col1!=col2) && (0.5*dist < radius) )
  1668.         col2 = col1;
  1669.     }
  1670.  
  1671.     if( src->flag & SphereFlag )
  1672.     {   radius = src->radius*Scale;
  1673.     if( dist <= radius ) return;
  1674.  
  1675.     /* Test for furthest half obscured! */
  1676.     if( (col1!=col2) && (0.5*dist < radius) )
  1677.         col1 = col2;
  1678.     }
  1679.  
  1680.     if( !VectSolid )
  1681.     {   fputs("[] 0 setdash\n",OutFile);
  1682.         VectSolid = True;
  1683.     }
  1684.  
  1685.     temp = ((src->z-ZOffset)+(dst->z-ZOffset))/ImageSize + 1.0;
  1686.     if( temp != LineWidth )
  1687.     {   fprintf(OutFile,"%g setlinewidth\n",temp);
  1688.     LineWidth = temp;
  1689.     }
  1690.  
  1691.     radius = rad*Scale;
  1692.     angle = Rad2Deg*atan2((double)dy,(double)dx);
  1693.     inten = (int)((dist/dist3)*ColourMask);
  1694.  
  1695.     if( col1 != col2 )
  1696.     {   midx = 0.5*(src->x + dst->x);
  1697.     midy = 0.5*(src->y + dst->y);
  1698.     relx = (radius*dx)/dist;
  1699.     rely = (radius*dy)/dist;
  1700.  
  1701.     fprintf(OutFile,"%g %g moveto\n",midx+rely,midy-relx);
  1702.     fprintf(OutFile,"%g %g lineto\n",midx-rely,midy+relx);
  1703.  
  1704.     ratio = dz/dist3;
  1705.  
  1706.     if( (src->flag&SphereFlag) && (src->radius>rad) )
  1707.     {   temp = (Scale*src->radius)/dist3;
  1708.         endx = src->x + temp*dx;
  1709.         endy = src->y + temp*dy;
  1710.  
  1711.         fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1712.         fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
  1713.     } else
  1714.     {   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
  1715.         fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
  1716.     }
  1717.     fputs("closepath ",OutFile);
  1718.  
  1719.     i = col1 + inten;
  1720.     fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
  1721.     fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
  1722.     fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
  1723.     fputs("setrgbcolor fill\n",OutFile);
  1724.  
  1725.     fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
  1726.     fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
  1727.     fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1728.     fprintf(OutFile,"%g %g StickEnd\n",midx,midy);
  1729.     fputs("closepath ",OutFile);
  1730.  
  1731.     i = col2 + inten;
  1732.     fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
  1733.     fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
  1734.     fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
  1735.     fputs("setrgbcolor fill\n",OutFile);
  1736.  
  1737.     if( UseOutLine )
  1738.     {   fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
  1739.         fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
  1740.         if( (src->flag&SphereFlag) && (src->radius>rad) )
  1741.         {   fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1742.         fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
  1743.         } else
  1744.         {   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
  1745.         fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
  1746.         }
  1747.         fputs("closepath 0 setgray stroke\n",OutFile);
  1748.     }
  1749.     } else /* col1 == col2! */
  1750.     {   fprintf(OutFile,"%d %d %g ",dst->x,dst->y,radius);
  1751.     fprintf(OutFile,"%g %g arc\n",angle-90,angle+90);
  1752.  
  1753.     if( (src->flag&SphereFlag) && (src->radius>rad) )
  1754.     {   temp = (Scale*src->radius)/dist3;
  1755.         endx = src->x + temp*dx;
  1756.         endy = src->y + temp*dy;
  1757.         ratio = dz/dist3;
  1758.  
  1759.         fprintf(OutFile,"%g %g %g ",radius,ratio,angle);
  1760.         fprintf(OutFile,"%g %g StickEnd\n",endx,endy);
  1761.     } else
  1762.     {   fprintf(OutFile,"%d %d %g ",src->x,src->y,radius);
  1763.         fprintf(OutFile,"%g %g arc\n",angle+90,angle-90);
  1764.     }
  1765.  
  1766.     i = col1 + inten;
  1767.     fprintf(OutFile,"%g ",(Real)RLut[i]/255.0);
  1768.     fprintf(OutFile,"%g ",(Real)GLut[i]/255.0);
  1769.     fprintf(OutFile,"%g ",(Real)BLut[i]/255.0);
  1770.     fputs("Stick\n",OutFile);
  1771.     }
  1772.     VectCol = 0;
  1773. }
  1774.  
  1775.  
  1776. static void WriteVectDots()
  1777. {
  1778.     register DotStruct __far *ptr;
  1779.     register Real x,y,z;
  1780.     register Real xi,yi;
  1781.     register int inten;
  1782.     register int temp;
  1783.     register int zi;
  1784.     register int i;
  1785.  
  1786.  
  1787.     if( LineWidth != 1.0 )
  1788.     {   fputs("1 setlinewidth\n",OutFile);
  1789.     LineWidth = 1.0;
  1790.     }
  1791.  
  1792.     temp = SlabValue - ZOffset;
  1793.     for( ptr=DotPtr; ptr; ptr=ptr->next )
  1794.     for( i=0; i<ptr->count; i++ )
  1795.     {   x = ptr->xpos[i];  
  1796.         y = ptr->ypos[i];  
  1797.         z = ptr->zpos[i];
  1798.  
  1799.  
  1800.         xi = (x*MatX[0]+y*MatX[1]+z*MatX[2]) + XOffset;
  1801.         if( (xi<0.0) || (xi>=XRange) ) continue;
  1802.         yi = (x*MatY[0]+y*MatY[1]+z*MatY[2]) + YOffset;
  1803.         if( (yi<0.0) || (yi>=YRange) ) continue;
  1804.  
  1805.         zi = (int)(x*MatZ[0]+y*MatZ[1]+z*MatZ[2]);
  1806.         if( UseSlabPlane && (zi>=temp) ) continue;
  1807.  
  1808.         inten = (ColourDepth*(zi+ImageRadius))/ImageSize;
  1809.         WriteVectColour( ptr->col[i]+inten );
  1810.         fprintf(OutFile,"%g %g Dot\n",xi,yi);
  1811.     }
  1812. }
  1813.  
  1814.  
  1815. static void WriteVectLabels()
  1816. {
  1817.     register Chain __far *chain;
  1818.     register Group __far *group;
  1819.     register Atom __far *aptr;
  1820.     register Label *label;
  1821.     auto char buffer[80];
  1822.  
  1823.     fputs("/Times-Roman",OutFile); /* Courier or Courier-Bold? */
  1824.     fprintf(OutFile," findfont %d scalefont setfont\n",FontSize<<1);
  1825.  
  1826.     if( UseLabelCol )
  1827.     {   if( BackR || BackG || BackB )
  1828.     {   fprintf(OutFile,"%g %g %g setrgbcolor\n",
  1829.             LabR/250.0, LabG/250.0, LabB/250.0);
  1830.     } else fputs("0 setgray\n",OutFile);
  1831.     } else VectCol = 0;
  1832.  
  1833.     ForEachAtom
  1834.     if( aptr->label )
  1835.     {   if( !UseLabelCol && (aptr->col!=VectCol) )
  1836.          WriteVectColour( aptr->col );
  1837.  
  1838.         label = (Label*)aptr->label;
  1839.         FormatLabel(chain,group,aptr,label->label,buffer);
  1840.         fprintf(OutFile,"(%s) %d %d Label\n",buffer,aptr->x,aptr->y);
  1841.     }
  1842. }
  1843.  
  1844.  
  1845. static Long CountPSItems()
  1846. {
  1847.     register Chain __far *chain;
  1848.     register Group __far *group;
  1849.     register HBond __far *hptr;
  1850.     register Bond __far *bptr;
  1851.     register Atom __far *aptr;
  1852.     register Long result;
  1853.  
  1854.     result = 0;
  1855.     if( DrawAtoms )
  1856.         ForEachAtom 
  1857.         if( aptr->flag&SphereFlag ) 
  1858.             if( !UseClipping || !ClipVectSphere(aptr) )
  1859.             result++;
  1860.  
  1861.     if( DrawBonds )
  1862.         ForEachBond 
  1863.             if( bptr->flag&DrawBondFlag && (!UseClipping ||
  1864.             !ClipVectBond(bptr->srcatom,bptr->dstatom)) )
  1865.             result++;
  1866.  
  1867.     ForEachBack 
  1868.         if( bptr->flag&DrawBondFlag && (!UseClipping ||
  1869.         !ClipVectBond(bptr->srcatom,bptr->dstatom)) )
  1870.         result++;
  1871.  
  1872.     for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
  1873.         if( hptr->flag&DrawBondFlag )
  1874.         {   if( HBondMode )
  1875.             {   if( !ClipVectBond(hptr->srcCA,hptr->dstCA) )
  1876.                     result++;
  1877.             } else if( !ClipVectBond(hptr->src,hptr->dst) )
  1878.                 result++;
  1879.         }
  1880.  
  1881.     for( hptr=Database->slist; hptr; hptr=hptr->hnext )
  1882.         if( hptr->flag&DrawBondFlag )
  1883.         {   if( SSBondMode )
  1884.             {   if( !ClipVectBond(hptr->srcCA,hptr->dstCA) )
  1885.                     result++;
  1886.             } else if( !ClipVectBond(hptr->src,hptr->dst) )
  1887.                 result++;
  1888.         }
  1889.     return( result );
  1890. }
  1891.  
  1892.  
  1893. static void FetchPSItems( data, type )
  1894.     PSItemPtr __far *data;
  1895.     char __far *type;
  1896. {
  1897.     register Chain __far *chain;
  1898.     register Group __far *group;
  1899.     register HBond __far *hptr;
  1900.     register Bond __far *bptr;
  1901.     register Atom __far *aptr;
  1902.     register int i,flag;
  1903.  
  1904.     i = 0;
  1905.     if( DrawAtoms )
  1906.         ForEachAtom
  1907.         if( aptr->flag&SphereFlag )
  1908.             if( !UseClipping || !ClipVectSphere(aptr) )
  1909.             {   type[i] = PSAtom; 
  1910.             data[i++] = aptr;
  1911.             }
  1912.  
  1913.     if( DrawBonds )
  1914.         ForEachBond
  1915.             if( bptr->flag&DrawBondFlag && (!UseClipping ||
  1916.             !ClipVectBond(bptr->srcatom,bptr->dstatom)) )
  1917.         {   type[i] = PSBond;
  1918.             data[i++] = bptr;
  1919.         } 
  1920.  
  1921.     ForEachBack
  1922.        if( bptr->flag&DrawBondFlag && (!UseClipping ||
  1923.            !ClipVectBond(bptr->srcatom,bptr->dstatom)) )
  1924.        {   type[i] = PSBond;
  1925.            data[i++] = bptr; 
  1926.        } 
  1927.  
  1928.     for( hptr=Database->hlist; hptr; hptr=hptr->hnext )
  1929.         if( hptr->flag&DrawBondFlag )
  1930.         {   if( HBondMode )
  1931.             {   flag = !ClipVectBond(hptr->srcCA,hptr->dstCA);
  1932.             } else flag = !ClipVectBond(hptr->src,hptr->dst);
  1933.  
  1934.             if( flag )
  1935.             {   type[i] = PSHBond;
  1936.                 data[i++] = hptr;
  1937.             }
  1938.         }
  1939.  
  1940.     for( hptr=Database->slist; hptr; hptr=hptr->hnext )
  1941.         if( hptr->flag&DrawBondFlag )
  1942.         {   if( SSBondMode )
  1943.             {   flag = !ClipVectBond(hptr->srcCA,hptr->dstCA);
  1944.             } else flag = !ClipVectBond(hptr->src,hptr->dst);
  1945.  
  1946.             if( flag )
  1947.             {   type[i] = PSSSBond;
  1948.                 data[i++] = hptr;
  1949.             }
  1950.         }
  1951. }
  1952.  
  1953.  
  1954. static void WritePSItems( data, type, count )
  1955.     PSItemPtr __far *data;
  1956.     char __far *type;
  1957.     int count;
  1958. {
  1959.     register HBond __far *hbond;
  1960.     register Bond __far *bond;
  1961.     register Atom __far *src;
  1962.     register Atom __far *dst;
  1963.     register int i;
  1964.  
  1965.     for( i=0; i<count; i++ )
  1966.         switch( type[i] )
  1967.         {   case(PSAtom):   WriteVectSphere(data,type,i);
  1968.                             break;
  1969.  
  1970.             case(PSBond):   bond = (Bond __far*)data[i];
  1971.                             src = bond->srcatom;
  1972.                             dst = bond->dstatom;
  1973.  
  1974.                             if( bond->flag & WireFlag )
  1975.                             {   WriteVectWire(src,dst,bond->col,False);
  1976.                             } else if( bond->flag & CylinderFlag )
  1977.                             {   WriteVectStick(src,dst,bond->col,bond->radius);
  1978.                             } else /* bond->flag & DashFlag */
  1979.                                 WriteVectWire(src,dst,bond->col,True);
  1980.                             break;
  1981.  
  1982.             case(PSSSBond): 
  1983.             case(PSHBond):  hbond = (HBond __far*)data[i];
  1984.                             if( (type[i]==PSHBond)? HBondMode : SSBondMode )
  1985.                             {   src = hbond->srcCA;
  1986.                                 dst = hbond->dstCA;
  1987.                             } else
  1988.                             {   src = hbond->src;
  1989.                                 dst = hbond->dst;
  1990.                             }
  1991.  
  1992.                             if( hbond->flag & WireFlag )
  1993.                             {   WriteVectWire(src,dst,hbond->col,True);
  1994.                             } else /* bond->flag & CylinderFlag */
  1995.                                 WriteVectStick(src,dst,hbond->col,
  1996.                                                        hbond->radius);
  1997.                             break;
  1998.         }
  1999. }
  2000.  
  2001.  
  2002.  
  2003. int WriteVectPSFile( name )
  2004.     char *name;
  2005. {
  2006.     register Real ambi;
  2007.     register Real temp, inten;
  2008.     register int xsize, ysize;
  2009.     register int xpos, ypos;
  2010.     register Long count;
  2011.     register int i;
  2012.  
  2013.     PSItemPtr __far *data;
  2014.     char __far *type;
  2015.  
  2016.     count = CountPSItems();
  2017.     if( !count ) return( True );
  2018.  
  2019. #ifdef IBMPC
  2020.     if( count > 16383 )
  2021.     {   if( CommandActive ) WriteChar('\n');
  2022.         WriteString("Output Error: Too many PostScript objects!\n");
  2023.         CommandActive = False;
  2024.     return( False );
  2025.     }
  2026. #endif
  2027.  
  2028.     /* Allocate arrays for objects! */
  2029.     data = (PSItemPtr __far*)_fmalloc((size_t)count*sizeof(PSItemPtr));
  2030.     type = (char __far*)_fmalloc((size_t)count*sizeof(char));
  2031.     if( !data || !type )
  2032.     {   if( CommandActive ) WriteChar('\n');
  2033.     WriteString("Output Error: Not enough memory to create PostScript!\n");
  2034.     CommandActive = False;
  2035.  
  2036.     if( data ) _ffree( data );
  2037.     if( type ) _ffree( type );
  2038.     return( False );
  2039.     }
  2040.  
  2041.     OutFile = fopen(name,"w");
  2042.     if( !OutFile )
  2043.     {   FatalOutputError(name);
  2044.     return(False);
  2045.     }
  2046.  
  2047.     /* Determine the size of the image */
  2048.     ysize = (int)(YRange*(BORDER*PAGEWIDE)/XRange);
  2049.     if( ysize > (int)(BORDER*PAGEHIGH) )
  2050.     {   xsize = (int)(XRange*(BORDER*PAGEHIGH)/YRange);
  2051.     ysize = (int)(BORDER*PAGEHIGH);
  2052.     } else xsize = (int)(BORDER*PAGEWIDE);
  2053.  
  2054.     xpos = (int)(PAGEWIDE-xsize)/2;
  2055.     ypos = (int)(PAGEHIGH-ysize)/2;
  2056.  
  2057.     fputs("%!PS-Adobe-2.0 EPSF-2.0\n",OutFile);
  2058.     fputs("%%Creator: RasMol Version 2.6\n",OutFile);
  2059.     fprintf(OutFile,"%%%%Title: %s\n",name);
  2060.     fprintf(OutFile,"%%%%BoundingBox: %d %d ",xpos,ypos);
  2061.     fprintf(OutFile,"%d %d\n",xpos+xsize,ypos+ysize);
  2062.  
  2063.     fputs("%%Pages: 1\n",OutFile);
  2064.     fputs("%%EndComments\n",OutFile);
  2065.     fputs("%%EndProlog\n",OutFile);
  2066.     fputs("%%BeginSetup\n",OutFile);
  2067.  
  2068.     fputs("1 setlinecap 1 setlinejoin [] 0 setdash\n",OutFile);
  2069.     fputs("1 setlinewidth 0 setgray\n",OutFile);
  2070.     fputs("%%EndSetup\n",OutFile);
  2071.     fputs("%%Page: 1 1\n",OutFile);
  2072.  
  2073.     fputs("gsave\n",OutFile);
  2074.     fputs("14 dict begin\n\n",OutFile);
  2075.     fputs("/handleerror { showpage } def\n\n",OutFile);
  2076.     fputs("/Inten {\n  dup 4 index mul exch\n",OutFile);
  2077.     fputs("  dup 4 index mul exch\n",OutFile);
  2078.     fputs("  3 index mul setrgbcolor\n} def\n\n",OutFile);
  2079.  
  2080.     fputs("/Dot {\n  moveto 0 0 rlineto stroke\n} def\n\n",OutFile);
  2081.     fputs("/Wire {\n  moveto lineto stroke\n} def\n\n",OutFile);
  2082. #ifdef INVERT
  2083.     fputs("/Label {\n  moveto show\n} def\n\n",OutFile);
  2084. #else
  2085.     fputs("/Label {\n  moveto 1 -1 scale\n",OutFile);
  2086.     fputs("  show mtrx setmatrix\n} def\n\n",OutFile);
  2087. #endif
  2088.  
  2089.     if( UseOutLine )
  2090.     {   fputs("/Stick {\n  closepath gsave setrgbcolor fill\n",OutFile);
  2091.     fputs("  grestore 0 setgray stroke\n} def\n\n",OutFile);
  2092.     } else
  2093.     fputs("/Stick {\n  closepath setrgbcolor fill\n} def\n\n",OutFile);
  2094.  
  2095.     fputs("/StickEnd {\n  matrix currentmatrix 6 1 roll\n",OutFile);
  2096.     fputs("  translate rotate 1 scale\n",OutFile);
  2097.     fputs("  0 0 3 2 roll 90 -90 arc\n  setmatrix\n} def\n\n",OutFile);
  2098.  
  2099.     if( UseOutLine )
  2100.     {   fputs("/Shade {\n  closepath gsave clip\n",OutFile);
  2101.     } else fputs("/Shade {\n  closepath clip\n",OutFile);
  2102.  
  2103.     if( Ambient < 0.99 )
  2104.     {   ambi = 0.5*Ambient;
  2105.         fputs("  45 rotate dup -0.81649658092 mul scale\n",OutFile);
  2106.         fprintf(OutFile,"  %g Inten fill\n",ambi);
  2107.         inten = (1.0-ambi)/31;
  2108.         for( i=0; i<31; i++ )
  2109.         {   temp = (Real)(i+1)/32;
  2110.         fprintf(OutFile,"  0 %g ",(Real)i/32);
  2111.         fprintf(OutFile,"%g 0 360 arc ",sqrt(1.0-temp*temp));
  2112.         fprintf(OutFile,"%g Inten fill\n",i*inten+ambi);
  2113.         }
  2114.         if( UseOutLine )
  2115.         {   fputs("  grestore 0 setgray stroke",OutFile);
  2116.         } else fputc(' ',OutFile);
  2117.         fputs(" pop pop pop\n} def\n\n",OutFile);
  2118.  
  2119.     } else /* Saturated Colours! */
  2120.     {   fputs("  pop setrgbcolor fill\n",OutFile);
  2121.         if( UseOutLine )
  2122.             fputs("  grestore 0 setgray stroke\n",OutFile);
  2123.         fputs("} def\n\n",OutFile);
  2124.     }
  2125.  
  2126.  
  2127.     fputs("/ClipSphere {\n  translate 0 0 5 2 roll arc\n} def\n\n",OutFile);
  2128.     fputs("/ClipBox {\n  translate rotate\n  dup lineto dup neg ",OutFile);
  2129.     fputs("dup\n  0 rlineto 0 exch rlineto 0 rlineto closepath\n",OutFile);
  2130.     fputs("  clip newpath mtrx setmatrix\n} def\n\n",OutFile);
  2131.     fputs("/ClipEllips {\n  translate rotate 1 scale\n",OutFile);
  2132.     fputs("  0 0 4 2 roll dup neg arc\n",OutFile);
  2133.     fputs("  reversepath mtrx setmatrix\n} def\n\n",OutFile);
  2134.  
  2135.     fputs("/Sphere {\n  gsave\n",OutFile);
  2136.     fputs("  translate 0 0 2 index 0 360 arc\n",OutFile);
  2137.     if( UseOutLine )
  2138.     {   fputs("  gsave Shade grestore\n",OutFile);
  2139.     fputs("  0 setgray stroke\n",OutFile);
  2140.     fputs("  grestore\n} def\n\n",OutFile);
  2141.     } else
  2142.     fputs("  Shade grestore\n} def\n\n",OutFile);
  2143.  
  2144. #ifdef INVERT
  2145.     fprintf(OutFile,"%d %d translate\n",xpos,ypos);
  2146.     fprintf(OutFile,"%g ",(Real)xsize/XRange);
  2147.     fprintf(OutFile,"%g ",(Real)ysize/YRange);
  2148. #else
  2149.     fprintf(OutFile,"%d %d translate\n",xpos,ypos+ysize);
  2150.     fprintf(OutFile,"%g ",(Real)xsize/XRange);
  2151.     fprintf(OutFile,"%g ",(Real)-ysize/YRange);
  2152. #endif
  2153.     fputs("scale\n/mtrx matrix currentmatrix def\n\n",OutFile);
  2154.  
  2155.     fputs("newpath 0 0 moveto 0 ",OutFile);
  2156.     fprintf(OutFile,"%d rlineto %d 0 rlineto 0 %d",YRange,XRange,-YRange);
  2157.     fputs(" rlineto\nclosepath clip ",OutFile);
  2158.     if( BackR || BackG || BackB )
  2159.     {   fprintf(OutFile,"%g %g %g",BackR/255.0,BackG/255.0,BackB/255.0);
  2160.     fputs(" setrgbcolor fill\n\n",OutFile);
  2161.     } else fputs("newpath\n\n",OutFile);
  2162.  
  2163.     LineWidth = 1.0;
  2164.     VectSolid = True;
  2165.     VectCol = 0;
  2166.  
  2167.     FetchPSItems(data,type);
  2168.     if( count>1 )
  2169.     DepthSort(data,type,(int)count);
  2170.  
  2171.     WritePSItems(data,type,(int)count);
  2172.  
  2173.     if( !VectSolid )
  2174.     {   fputs("[] 0 setdash\n",OutFile);
  2175.         VectSolid = True;
  2176.     }
  2177.  
  2178.     if( DrawDots )
  2179.     WriteVectDots();
  2180.     if( DrawLabels )
  2181.     WriteVectLabels();
  2182.  
  2183.     fputs("newpath 0 0 moveto 0 ",OutFile);
  2184.     fprintf(OutFile,"%d rlineto %d 0 rlineto 0 %d",YRange,XRange,-YRange);
  2185.     fputs(" rlineto\nclosepath 0 setgray 1 setlinewidth stroke\n",OutFile);
  2186.     fputs("end grestore\nshowpage\n",OutFile);
  2187.     fputs("%%Trailer\n",OutFile);
  2188.     fputs("%%EOF\n",OutFile);
  2189.  
  2190.     fclose( OutFile );
  2191. #ifdef APPLEMAC
  2192.     /* Avoid ANSI trigraph problems! */
  2193.     SetFileInfo(name,'vgrd','TEXT',134);
  2194. #endif
  2195.     _ffree( data );
  2196.     _ffree( type );
  2197.     return(True);
  2198. }
  2199.  
  2200.  
  2201.  
  2202. static void FlushPICTBuffer()
  2203. {
  2204.     if( PacketLen )
  2205.     {   if( RLEOutput )
  2206.         {   WriteByte(PacketLen-1);
  2207.             fwrite((char*)Buffer,1,PacketLen,OutFile);
  2208.         } else RLELineSize += PacketLen+1;
  2209.         PacketLen = 0;
  2210.     }
  2211. }
  2212.  
  2213.  
  2214. static void FlushPICTPacket()
  2215. {
  2216.     register int i;
  2217.  
  2218.     if( RLELength>2 )
  2219.     {   FlushPICTBuffer();
  2220.  
  2221.     if( RLEOutput )
  2222.     {   WriteByte(257-RLELength);
  2223.         WriteByte(RLEChar);
  2224.     } else RLELineSize += 2;
  2225.     } else 
  2226.     for( i=0; i<RLELength; i++ )
  2227.     {   Buffer[PacketLen++] = RLEChar;
  2228.         if( PacketLen == 128 ) 
  2229.         FlushPICTBuffer();
  2230.     }
  2231. }
  2232.  
  2233.  
  2234. static void WritePICTCode( val )
  2235.     int val;
  2236. {
  2237.     if( !RLELength )
  2238.     {   RLEChar = val;
  2239.     RLELength = 1;
  2240.     } else if( (val!=RLEChar) || (RLELength==128) )
  2241.     {   FlushPICTPacket();
  2242.     RLEChar = val;
  2243.     RLELength = 1;
  2244.     } else RLELength++;
  2245. }
  2246.  
  2247. static void WritePICTData()
  2248. {
  2249. #ifndef EIGHTBIT
  2250.     register Pixel data;
  2251. #endif
  2252.     register Pixel __huge *ptr;
  2253.     register Pixel __huge *tmp;
  2254.     register int rowbytes;
  2255.     register int x,y;
  2256.  
  2257. #ifdef IBMPC
  2258.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  2259. #endif
  2260.  
  2261. #ifdef EIGHTBIT
  2262.     rowbytes = XRange;
  2263. #else
  2264.     rowbytes = XRange*3;
  2265. #endif
  2266.  
  2267.     RLEFileSize = 0;
  2268.  
  2269. #ifndef INVERT
  2270.     ptr = FBuffer;
  2271. #endif
  2272.     for( y=YRange-1; y>=0; y-- )
  2273.     {
  2274. #ifdef INVERT
  2275.     ptr = FBuffer + (Long)y*XRange;
  2276. #endif
  2277.  
  2278.     RLELineSize = 0;
  2279.     RLEOutput = False;
  2280.     PacketLen = 0;
  2281.     RLELength = 0;
  2282.  
  2283. #ifdef EIGHTBIT
  2284.     tmp = ptr;
  2285.     for( x=0; x<XRange; x++ )
  2286.         WritePICTCode( LutInv[*tmp++] );
  2287. #else
  2288.     tmp = ptr;
  2289.     for( x=0; x<XRange; x++ )
  2290.         WritePICTCode( (int)RComp(*tmp++) );
  2291.     tmp = ptr;
  2292.     for( x=0; x<XRange; x++ )
  2293.         WritePICTCode( (int)GComp(*tmp++) );
  2294.     tmp = ptr;
  2295.     for( x=0; x<XRange; x++ )
  2296.         WritePICTCode( (int)BComp(*tmp++) );
  2297. #endif
  2298.     FlushPICTPacket();
  2299.     FlushPICTBuffer();
  2300.  
  2301. #ifdef EIGHTBIT
  2302.     if( rowbytes > 250 )
  2303.     {   WriteMSBShort(RLELineSize);
  2304.         RLEFileSize += (RLELineSize+2);
  2305.     } else
  2306.     {   WriteByte(RLELineSize);
  2307.         RLEFileSize += (RLELineSize+1);
  2308.     }
  2309. #else
  2310.     WriteMSBShort(RLELineSize);
  2311.     RLEFileSize += (RLELineSize+2);
  2312. #endif
  2313.  
  2314.     RLEOutput = True;
  2315.     PacketLen = 0;
  2316.     RLELength = 0;
  2317.  
  2318. #ifdef EIGHTBIT
  2319.     for( x=0; x<XRange; x++ )
  2320.         WritePICTCode( LutInv[*ptr++] );
  2321. #else
  2322.     tmp = ptr;
  2323.     for( x=0; x<XRange; x++ )
  2324.         WritePICTCode( (int)RComp(*tmp++) );
  2325.     tmp = ptr;
  2326.     for( x=0; x<XRange; x++ )
  2327.         WritePICTCode( (int)GComp(*tmp++) );
  2328.     for( x=0; x<XRange; x++ )
  2329.         WritePICTCode( (int)BComp(*ptr++) );
  2330. #endif
  2331.     FlushPICTPacket();
  2332.     FlushPICTBuffer();
  2333.     }
  2334.  
  2335. #ifdef IBMPC
  2336.     GlobalUnlock(FBufHandle);
  2337. #endif
  2338. }
  2339.  
  2340.  
  2341. int WritePICTFile( name )
  2342.     char *name;
  2343. {
  2344. #ifdef EIGHTBIT
  2345.     register int j,r,g,b;
  2346. #endif
  2347.     register int cols;
  2348.     register int i;
  2349.  
  2350. #if defined(IBMPC) || defined(APPLEMAC)
  2351.     OutFile = fopen(name,"wb");
  2352. #else
  2353.     OutFile = fopen(name,"w");
  2354. #endif
  2355.     if( !OutFile )
  2356.     {    FatalOutputError(name);
  2357.      return( False );
  2358.     }
  2359.  
  2360. #ifdef EIGHTBIT
  2361.     cols = CompactColourMap();
  2362. #endif
  2363.  
  2364.     /* Write out header */
  2365.     for( i=0; i<512; i++ )
  2366.     WriteByte( 0x00 );
  2367.  
  2368.     WriteMSBShort(0);       /* picSize         */
  2369.     WriteMSBShort(0);       /* picFrame.top    */
  2370.     WriteMSBShort(0);       /* picFrame.left   */
  2371.     WriteMSBShort(YRange);  /* picFrame.bottom */
  2372.     WriteMSBShort(XRange);  /* picFrame.right  */
  2373.  
  2374.     WriteMSBShort(PICTpicversion);
  2375.     WriteMSBShort(0x02FF);
  2376.  
  2377.     WriteMSBShort(PICTheaderop);
  2378.     WriteMSBLong((Card)0xffffffff);
  2379.     WriteMSBShort(0);      WriteMSBShort(0);
  2380.     WriteMSBShort(0);      WriteMSBShort(0);
  2381.     WriteMSBShort(XRange); WriteMSBShort(0);
  2382.     WriteMSBShort(YRange); WriteMSBShort(0);
  2383.     WriteMSBLong(0);
  2384.  
  2385.     WriteMSBShort(PICTcliprgn);
  2386.     WriteMSBShort(10);      /* rgnSize */
  2387.     WriteMSBShort(0);       /* rgnBBox.top    */
  2388.     WriteMSBShort(0);       /* rgnBBox.left   */
  2389.     WriteMSBShort(YRange);  /* rgnBBox.bottom */
  2390.     WriteMSBShort(XRange);  /* rgnBBox.right  */
  2391.  
  2392. #ifdef EIGHTBIT
  2393.     WriteMSBShort(PICTpackbitsrect);
  2394. #else
  2395.     WriteMSBShort(PICTdirectbitsrect);
  2396.     WriteMSBShort(0x0000);  /* baseAddr      */
  2397.     WriteMSBShort(0x00ff);
  2398. #endif
  2399.     i = (XRange*sizeof(Pixel)) | 0x8000;
  2400.     WriteMSBShort( i );     /* rowBytes      */
  2401.     WriteMSBShort(0);       /* bounds.top    */
  2402.     WriteMSBShort(0);       /* bounds.left   */
  2403.     WriteMSBShort(YRange);  /* bounds.bottom */
  2404.     WriteMSBShort(XRange);  /* bounds.right  */
  2405.     WriteMSBShort(0);       /* pmVersion     */
  2406. #ifdef EIGHTBIT
  2407.     WriteMSBShort(0);       /* packType      */
  2408. #else
  2409.     WriteMSBShort(4);       /* packType      */
  2410. #endif
  2411.     WriteMSBLong(0);        /* packSize      */
  2412.     WriteMSBLong(72);       /* hRes          */
  2413.     WriteMSBLong(72);       /* vRes          */
  2414.  
  2415. #ifdef EIGHTBIT
  2416.     WriteMSBShort(0);       /* pixelType     */
  2417.     WriteMSBShort(8);       /* pixelSize     */
  2418.     WriteMSBShort(1);       /* cmpCount      */
  2419.     WriteMSBShort(8);       /* cmpSize       */
  2420. #else
  2421.     WriteMSBShort(16);      /* pixelType     */
  2422.     WriteMSBShort(32);      /* pixelSize     */
  2423.     WriteMSBShort(3);       /* cmpCount      */
  2424.     WriteMSBShort(8);       /* cmpSize       */
  2425. #endif
  2426.  
  2427.     WriteMSBLong(0);        /* planeBytes    */
  2428.     WriteMSBLong(0);        /* pmTable       */
  2429.     WriteMSBLong(0);        /* pmReserved    */
  2430.  
  2431. #ifdef EIGHTBIT
  2432.     WriteMSBLong(0);        /* ctSeed        */
  2433.     WriteMSBShort(0);       /* ctFlags       */
  2434.     WriteMSBShort(cols-1);  /* ctSize        */
  2435.  
  2436.     for( i=0; i<cols; i++ )
  2437.     {    WriteMSBShort(i);  /* value */
  2438.      j=Node[i]; r=RLut[j]; g=GLut[j]; b=BLut[j];
  2439.      WriteMSBShort( (r<<8)|r );  /* rgb.red */
  2440.      WriteMSBShort( (g<<8)|g );  /* rgb.green */
  2441.      WriteMSBShort( (b<<8)|b );  /* rgb.blue  */
  2442.     }
  2443. #endif
  2444.  
  2445.     WriteMSBShort(0);       /* srcRect.top    */
  2446.     WriteMSBShort(0);       /* srcRect.left   */
  2447.     WriteMSBShort(YRange);  /* srcRect.bottom */
  2448.     WriteMSBShort(XRange);  /* srcRect.right  */
  2449.     WriteMSBShort(0);       /* dstRect.top    */
  2450.     WriteMSBShort(0);       /* dstRect.left   */
  2451.     WriteMSBShort(YRange);  /* dstRect.bottom */
  2452.     WriteMSBShort(XRange);  /* dstRect.right  */
  2453.     WriteMSBShort(0);       /* mode (srcCopy) */
  2454.  
  2455.     WritePICTData();
  2456.     if( RLEFileSize & 0x01 ) WriteByte(0x00);
  2457.     WriteMSBShort(PICTendofpict);
  2458.     fclose(OutFile);
  2459. #ifdef APPLEMAC
  2460.     SetFileInfo(name,'ttxt','PICT',134);
  2461. #endif
  2462.     return( True );
  2463. }
  2464.  
  2465.  
  2466. static void FlushIRISBuffer()
  2467. {
  2468.     if( PacketLen )
  2469.     {   if( RLEOutput )
  2470.         {   WriteByte(PacketLen|0x80);
  2471.             fwrite((char*)Buffer,1,PacketLen,OutFile);
  2472.         } else RLELineSize += PacketLen+1;
  2473.         PacketLen = 0;
  2474.     }
  2475. }
  2476.  
  2477.  
  2478. static void FlushIRISPacket()
  2479. {
  2480.     register int i;
  2481.  
  2482.     if( RLELength>2 )
  2483.     {   FlushIRISBuffer();
  2484.  
  2485.         if( RLEOutput )
  2486.         {   WriteByte(RLELength);
  2487.             WriteByte(RLEChar);
  2488.         } else RLELineSize += 2;
  2489.     } else
  2490.         for( i=0; i<RLELength; i++ )
  2491.         {   Buffer[PacketLen++] = RLEChar;
  2492.             if( PacketLen == 127 )
  2493.                 FlushIRISBuffer();
  2494.         }
  2495.     RLELength = 0;
  2496. }
  2497.  
  2498.  
  2499. static void WriteIRISCode( val )
  2500.     int val;
  2501. {
  2502.     if( !RLELength )
  2503.     {   RLELength = 1;
  2504.         RLEChar = val;
  2505.     } else if( (RLEChar!=val) || (RLELength==127) )
  2506.     {   FlushIRISPacket();
  2507.         RLELength = 1;
  2508.         RLEChar = val;
  2509.     } else RLELength++;
  2510. }
  2511.  
  2512.  
  2513. int WriteIRISFile( name )
  2514.     char *name;
  2515. {
  2516.     register Long __far *rowstart;
  2517.     register short __far *rowsize;
  2518.     register Pixel __huge *ptr;
  2519.     register Pixel __huge *tmp;
  2520.     register int i,min,max;
  2521.     register int x,y,size;
  2522.  
  2523.     size = 3*YRange;
  2524.     /* Allocate RLE encoded row length table */
  2525.     rowsize = (short __far*)_fmalloc(size*sizeof(short));
  2526.     rowstart = (Long __far*)_fmalloc(size*sizeof(Long));
  2527.  
  2528.     if( !rowsize || !rowstart )
  2529.     {   if( CommandActive ) WriteChar('\n');
  2530.         WriteString("Output Error: Unable to allocate memory!\n");
  2531.         if( rowstart ) _ffree(rowstart);
  2532.         if( rowsize ) _ffree(rowsize);
  2533.         CommandActive = False;
  2534.         return( False );
  2535.     }
  2536.  
  2537. #if defined(IBMPC) || defined(APPLEMAC)
  2538.     OutFile = fopen(name,"wb");
  2539. #else
  2540.     OutFile = fopen(name,"w");
  2541. #endif
  2542.     if( !OutFile )
  2543.     {    FatalOutputError(name);
  2544.      return( False );
  2545.     }
  2546.  
  2547.     CalcInvColourMap();
  2548.  
  2549. #ifdef IBMPC
  2550.     FBuffer = (Pixel __huge*)GlobalLock(FBufHandle);
  2551. #endif
  2552.  
  2553. #ifdef INVERT
  2554.     ptr = FBuffer;
  2555. #endif
  2556.  
  2557.     max = 0;
  2558.     min = 255;
  2559.     RLEFileSize = 512 + 2*size*sizeof(Long);
  2560.  
  2561.     RLEOutput = False;
  2562.     PacketLen = 0;
  2563.     RLELength = 0;
  2564.  
  2565.     for( y=0; y<YRange; y++ )
  2566.     {
  2567. #ifndef INVERT
  2568.         ptr = FBuffer + (Long)((YRange-1)-y)*XRange;
  2569. #endif
  2570.  
  2571.         tmp = ptr;
  2572.         RLELineSize = 0;
  2573.         /* Red Component */
  2574.         for( x=0; x<XRange; x++ )
  2575.         {   i = RComp(*ptr++);
  2576.             if( i<min ) min=i;
  2577.             if( i>max ) max=i;
  2578.             WriteIRISCode(i);
  2579.         }
  2580.         FlushIRISPacket();
  2581.         FlushIRISBuffer();
  2582.  
  2583.         rowsize[y] = RLELineSize;
  2584.         rowstart[y] = RLEFileSize;
  2585.         RLEFileSize += RLELineSize;
  2586.  
  2587.         ptr = tmp;
  2588.         RLELineSize = 0;
  2589.         /* Green Component */
  2590.         for( x=0; x<XRange; x++ )
  2591.         {   i = GComp(*ptr++);
  2592.             if( i<min ) min=i;
  2593.             if( i>max ) max=i;
  2594.             WriteIRISCode(i);
  2595.         }
  2596.         FlushIRISPacket();
  2597.         FlushIRISBuffer();
  2598.  
  2599.         i = y+YRange;
  2600.         rowsize[i] = RLELineSize;
  2601.         rowstart[i] = RLEFileSize;
  2602.         RLEFileSize += RLELineSize;
  2603.  
  2604.         ptr = tmp;
  2605.         RLELineSize = 0;
  2606.         /* Blue Component */
  2607.         for( x=0; x<XRange; x++ )
  2608.         {   i = BComp(*ptr++);
  2609.             if( i<min ) min=i;
  2610.             if( i>max ) max=i;
  2611.             WriteIRISCode(i);
  2612.         }
  2613.         FlushIRISPacket();
  2614.         FlushIRISBuffer();
  2615.  
  2616.         i = y+(YRange<<1);
  2617.         rowsize[i] = RLELineSize;
  2618.         rowstart[i] = RLEFileSize;
  2619.         RLEFileSize += RLELineSize;
  2620.     }
  2621.  
  2622.  
  2623.     WriteMSBShort(474);     /* imagic     */
  2624.     WriteMSBShort(257);     /* type       */
  2625.     WriteMSBShort(3);       /* dim        */
  2626.     WriteMSBShort(XRange);  /* xsize      */
  2627.     WriteMSBShort(YRange);  /* ysize      */
  2628.     WriteMSBShort(3);       /* zsize      */
  2629.     WriteMSBLong(min);      /* min        */
  2630.     WriteMSBLong(max);      /* max        */
  2631.     WriteMSBLong(0);        /* wastebytes */
  2632.  
  2633.                             /* name       */
  2634.     fputs("RasMol IRIS RGB format output",OutFile);
  2635.     for( i=0; i<51; i++ ) WriteByte(0x00);
  2636.     WriteMSBLong(0);        /* colormap   */
  2637.  
  2638.     for( i=0; i<404; i++ )  WriteByte(0x00);
  2639.     for( i=0; i<size; i++ ) WriteMSBLong(rowstart[i]);
  2640.     for( i=0; i<size; i++ ) WriteMSBLong(rowsize[i]);
  2641.  
  2642. #ifdef INVERT
  2643.     ptr = FBuffer;
  2644. #endif
  2645.  
  2646.     RLEOutput = True;
  2647.     for( y=0; y<YRange; y++ )
  2648.     {
  2649. #ifndef INVERT
  2650.         ptr = FBuffer + (Long)((YRange-1)-y)*XRange;
  2651. #endif
  2652.  
  2653.         tmp = ptr;
  2654.         /* Red Component */
  2655.         for( x=0; x<XRange; x++ )
  2656.         {   i = RComp(*ptr++);
  2657.             WriteIRISCode(i);
  2658.         }
  2659.         FlushIRISPacket();
  2660.         FlushIRISBuffer();
  2661.  
  2662.         ptr = tmp;
  2663.         /* Green Component */
  2664.         for( x=0; x<XRange; x++ )
  2665.         {   i = GComp(*ptr++);
  2666.             WriteIRISCode(i);
  2667.         }
  2668.         FlushIRISPacket();
  2669.         FlushIRISBuffer();
  2670.  
  2671.         ptr = tmp;
  2672.         /* Blue Component */
  2673.         for( x=0; x<XRange; x++ )
  2674.         {   i = BComp(*ptr++);
  2675.             WriteIRISCode(i);
  2676.         }
  2677.         FlushIRISPacket();
  2678.         FlushIRISBuffer();
  2679.     }
  2680.  
  2681.     _ffree( rowstart );
  2682.     _ffree( rowsize );
  2683.     fclose( OutFile );
  2684.  
  2685. #ifdef APPLEMAC
  2686.     /* Avoid ANSI trigraph problems! */
  2687.     SetFileInfo(name,'\?\?\?\?','\?\?\?\?',134);
  2688. #endif
  2689. #ifdef IBMPC
  2690.     GlobalUnlock(FBufHandle); 
  2691. #endif
  2692.     return( True );
  2693. }
  2694.  
  2695.  
  2696. void InitialiseOutFile()
  2697. {
  2698. #if defined(IBMPC) || defined(APPLEMAC)
  2699.     /* Allocate Tables on FAR Heap */
  2700.     ABranch = (short __far*)_fmalloc(4096*sizeof(short));
  2701.     DBranch = (short __far*)_fmalloc(4096*sizeof(short));
  2702.     Hash = (short __far*)_fmalloc(256*sizeof(short));
  2703.     Node = (Byte __far*)_fmalloc(4096*sizeof(Byte));
  2704. #endif
  2705.  
  2706.     KinemageFlag = False;
  2707.     UseOutLine = False;
  2708. }
  2709.